Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common 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/cpl-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. 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 CPL, 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 CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby.util;
 
 import static org.jcodings.Encoding.CHAR_INVALID;
 
 import org.jruby.Ruby;
 
 
 public final class StringSupport {
     public static final int CR_MASK      = . | .;  
     public static final int CR_UNKNOWN   = 0;
     public static final int CR_7BIT      = .
     public static final int CR_VALID     = .;
     public static final int CR_BROKEN    = . | .;
 
     public static final Object UNSAFE = getUnsafe();
     private static final int OFFSET =  != null ? ((Unsafe)).arrayBaseOffset(byte[].class) : 0;
 
     private static Object getUnsafe() {
         try {
             Class sunUnsafe = Class.forName("sun.misc.Unsafe");
             java.lang.reflect.Field f = sunUnsafe.getDeclaredField("theUnsafe");
             f.setAccessible(true);
             return sun.misc.Unsafe.class.cast(f.get(sunUnsafe));
         } catch (Exception ex) {
             return null;
         }
     }
     
     public static String codeRangeAsString(int codeRange) {
         switch (codeRange) {
             case return "unknown";
             case return "7bit";
             case return "valid";
             case return "broken";
         }
         
         return "???";  // Not reached unless something seriously boned
     }
 
     // rb_enc_mbclen
     public static int length(Encoding encbyte[]bytesint pint end) {
         int n = enc.length(bytespend);
         if (n > 0 && end - p >= nreturn n;
         return end - p >= enc.minLength() ? enc.minLength() : end - p;
     }
 
     // rb_enc_precise_mbclen
     public static int preciseLength(Encoding encbyte[]bytesint pint end) {
         if (p >= endreturn -1 - (1);
         int n = enc.length(bytespend);
         if (n > end - preturn -1 - (n - (end - p));
         return n;
     }
     
     public static int searchNonAscii(byte[]bytesint pint end) {
         while (p < end) {
             if (!Encoding.isAscii(bytes[p])) return p;
             p++;
         }
         return -1;
     }
 
     public static int searchNonAscii(ByteList bytes) { 
         return searchNonAscii(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
     }
 
     public static int codeRangeScan(Encoding encbyte[]bytesint pint len) {
        if (enc == .) {
            return searchNonAscii(bytespp + len) != -1 ?  : ;
        }
        if (enc.isAsciiCompatible()) {
            return codeRangeScanAsciiCompatible(encbytesplen);
        }
        return codeRangeScanNonAsciiCompatible(encbytesplen);
    }
    private static int codeRangeScanAsciiCompatible(Encoding encbyte[]bytesint pint len) {
        int end = p + len;
        p = searchNonAscii(bytespend);
        if (p == -1) return ;
        
        while (p < end) {
            int cl = preciseLength(encbytespend);
            if (cl <= 0) return ;
            p += cl;
            if (p < end) {
                p = searchNonAscii(bytespend);
                if (p == -1) return ;
            }
        }
        return p > end ?  : ;
    }
    
    private static int codeRangeScanNonAsciiCompatible(Encoding encbyte[]bytesint pint len) {
        int end = p + len;
        while (p < end) {        
            int cl = preciseLength(encbytespend);
            if (cl <= 0) return ;
            p += cl;
        }
        return p > end ?  : ;
    }
    public static int codeRangeScan(Encoding encByteList bytes) {
        return codeRangeScan(encbytes.getUnsafeBytes(), bytes.getBegin(), bytes.getRealSize());
    }
    public static long codeRangeScanRestartable(Encoding encbyte[]bytesint sint endint cr) { 
        if (cr == return pack(end - scr);
        int p = s;
        
        if (enc == .) {
            return pack(end - ssearchNonAscii(bytespend) == -1 && cr !=  ?  : );
        } else if (enc.isAsciiCompatible()) {
            p = searchNonAscii(bytespend);
            if (p == -1) return pack(end - scr !=  ?  : cr);
            while (p < end) {
                int cl = preciseLength(encbytespend);
                if (cl <= 0) return pack(p - scl ==  ?  : );
                p += cl;
                if (p < end) {
                    p = searchNonAscii(bytespend);
                    if (p == -1) return pack(end - s);
                }
            }
        } else {
            while (p < end) {
                int cl = preciseLength(encbytespend);
                if (cl <= 0) return pack(p - scl ==  ? );
                p += cl;
            }
        }
        return pack(p - sp > end ?  : );
    }
    private static final long NONASCII_MASK = 0x8080808080808080L;
    private static int countUtf8LeadBytes(long d) {
        d |= ~(d >>> 1);
        d >>>= 6;
        d &=  >>> 7;
        d += (d >>> 8);
        d += (d >>> 16);
        d += (d >>> 32);
        return (int)(d & 0xf);
    }
    private static final int LONG_SIZE = 8;
    private static final int LOWBITS =  - 1;
    @SuppressWarnings("deprecation")
    public static int utf8Length(byte[]bytesint pint end) {
        int len = 0;
        if ( != null) {
            if (end - p >  * 2) {
                int ep = ~ & (p + );
                while (p < ep) {
                    if ((bytes[p++] & 0xc0 /*utf8 lead byte*/) != 0x80) len++;
                }
                Unsafe us = (Unsafe);
                int eend = ~ & end;
                while (p < eend) {
                    len += countUtf8LeadBytes(us.getLong(bytes + p));
                    p += ;
                }
            }
        }
        while (p < end) {
            if ((bytes[p++] & 0xc0 /*utf8 lead byte*/) != 0x80) len++;
        }
        return len;
    }
    public static int utf8Length(ByteList bytes) {
        return utf8Length(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
    }
    public static int strLength(Encoding encbyte[]bytesint pint end) {
        if (enc.isFixedWidth()) {
            return (end - p + enc.minLength() - 1) / enc.minLength();
        } else if (enc.isAsciiCompatible()) {
            int c = 0;
            while (p < end) {
                if (Encoding.isAscii(bytes[p])) {
                    int q = searchNonAscii(bytespend);
                    if (q == -1) return c + (end - p);
                    c += q - p;
                    p = q;
                }
                p += length(encbytespend);
                c++;
            }
            return c;
        }
        
        int c;
        for (c = 0; end > pc++) p += length(encbytespend);
        return c;
    }
    public static int strLength(ByteList bytes) { 
        return strLength(bytes.getEncoding(), bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
    }
    public static long strLengthWithCodeRange(Encoding encbyte[]bytesint pint end) {
        if (enc.isFixedWidth()) {
            return (end - p + enc.minLength() - 1) / enc.minLength();
        } else if (enc.isAsciiCompatible()) {
            return strLengthWithCodeRangeAsciiCompatible(encbytespend);
        } else {
            return strLengthWithCodeRangeNonAsciiCompatible(encbytespend);
        }
    }
    private static long strLengthWithCodeRangeAsciiCompatible(Encoding encbyte[]bytesint pint end) {
        int cr = 0, c = 0;
        while (p < end) {
            if (Encoding.isAscii(bytes[p])) {
                int q = searchNonAscii(bytespend);
                if (q == -1) return pack(c + (end - p), cr == 0 ?  : cr);
                c += q - p;
                p = q;
            }
            int cl = preciseLength(encbytespend);
            if (cl > 0) {
                cr |= 
                p += cl;
            } else {
                cr = ;
                p++;
            }
            c++;
        }
        return pack(ccr == 0 ?  : cr);
    }
    private static long strLengthWithCodeRangeNonAsciiCompatible(Encoding encbyte[]bytesint pint end) {
        int cr = 0, c = 0;
        for (c = 0; p < endc++) {
            int cl = preciseLength(encbytespend);
            if (cl > 0) {
                cr |= 
                p += cl;
            } else {
                cr = ;
                p++;
            }
        }
        return pack(ccr == 0 ?  : cr);
    }
    public static long strLengthWithCodeRange(ByteList bytes) { 
        return strLengthWithCodeRange(bytes.getEncoding(), bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
    }
    public static long strLengthWithCodeRange(ByteList bytesEncoding enc) { 
        return strLengthWithCodeRange(encbytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
    }
    // arg cannot be negative
    static long pack(int resultint arg) {
        return ((long)arg << 31) | result;
    }
    public static int unpackResult(long len) {
        return (int)len & 0x7fffffff;
    }
    public static int unpackArg(long cr) {
        return (int)(cr >>> 31);
    }
    public static int codePoint(Ruby runtimeEncoding encbyte[]bytesint pint end) {
        if (p >= endthrow runtime.newArgumentError("empty string");
        int cl = preciseLength(encbytespend);
        if (cl <= 0) throw runtime.newArgumentError("invalid byte sequence in " + enc); 
        return enc.mbcToCode(bytespend); 
    }
    public static int codeLength(Ruby runtimeEncoding encint c) {
        int n = enc.codeToMbcLength(c);
        if (n == 0) throw runtime.newArgumentError("invalid codepoint " + String.format("0x%x in "c) + enc.getName());
        return n;
    }
    public static long getAscii(Encoding encbyte[]bytesint pint end) {
        return getAscii(encbytespend, 0);
    }
    public static long getAscii(Encoding encbyte[]bytesint pint endint len) {
        if (p >= endreturn pack(-1, len);
        if (enc.isAsciiCompatible()) {
            int c = bytes[p] & 0xff;
            if (!Encoding.isAscii(c)) return pack(-1, len);
            return pack(clen == 0 ? 0 : 1);
        } else {
            int cl = preciseLength(encbytespend);
            if (cl <= 0) return pack(-1, len);
            int c = enc.mbcToCode(bytespend);
            if (!Encoding.isAscii(c)) return pack(-1, len);
            return pack(clen == 0 ? 0 : cl);
        }
    }
    public static int preciseCodePoint(Encoding encbyte[]bytesint pint end) {
        int l = preciseLength(encbytespend);
        if (l > 0) enc.mbcToCode(bytespend);
        return -1;
    }
    @SuppressWarnings("deprecation")
    public static int utf8Nth(byte[]bytesint pint endint n) {
        if ( != null) {
            if (n >  * 2) {
                int ep = ~ & (p + );
                while (p < ep) {
                    if ((bytes[p++] & 0xc0 /*utf8 lead byte*/) != 0x80) n--;
                }
                Unsafe us = (Unsafe);
                int eend = ~ & end;
                do {
                    n -= countUtf8LeadBytes(us.getLong(bytes + p));
                    p += ;
                } while (p < eend && n >= );
            }
        }
        while (p < end) {
            if ((bytes[p] & 0xc0 /*utf8 lead byte*/) != 0x80) {
                if (n-- == 0) break;
            }
            p++;
        }
        return p;
    }
    public static int nth(Encoding encbyte[]bytesint pint endint n) {
        if (enc.isSingleByte()) {
            p += n;
        } else if (enc.isFixedWidth()) {
            p += n * enc.maxLength();             
        } else if (enc.isAsciiCompatible()) {
            p = nthAsciiCompatible(encbytespendn);
        } else {
            p = nthNonAsciiCompatible(encbytespendn);
        }
        return p > end ? end : p;
    }
    private static int nthAsciiCompatible(Encoding encbyte[]bytesint pint endint n) {
        while (p < end && n > 0) {
            int end2 = p + n;
            if (end < end2return end;
            if (Encoding.isAscii(bytes[p])) {
                int p2 = searchNonAscii(bytespend2);
                if (p2 == -1) return end2;
                n -= p2 - p;
                p = p2;
            }
            int cl = length(encbytespend);
            p += cl;
            n--;
        }
        return n != 0 ? end : p;
    }
    private static int nthNonAsciiCompatible(Encoding encbyte[]bytesint pint endint n) {
        while (p < end && n-- != 0) {
            p += length(encbytespend);
        }
        return p;
    }
    public static int utf8Offset(byte[]bytesint pint endint n) {
        int pp = utf8Nth(bytespendn);
        return pp == -1 ? end - p : pp - p
    }
    public static int offset(Encoding encbyte[]bytesint pint endint n) {
        int pp = nth(encbytespendn);
        return pp == -1 ? end - p : pp - p
    }
    public static int offset(RubyString strint pos) {
        ByteList value = str.getByteList();
        return offset(str.getEncoding(), value.getUnsafeBytes(), value.getBegin(), value.getBegin() + value.getRealSize(), pos);
    }
    public static int toLower(Encoding encint c) {
        return Encoding.isAscii(c) ? .[c] : c;
    }
    public static int toUpper(Encoding encint c) {
        return Encoding.isAscii(c) ? .[c] : c;
    }
    public static int caseCmp(byte[]bytes1int p1byte[]bytes2int p2int len) {
        int i = -1;
        for (; ++i < len && bytes1[p1 + i] == bytes2[p2 + i];) {}
        if (i < lenreturn (bytes1[p1 + i] & 0xff) > (bytes2[p2 + i] & 0xff) ? 1 : -1;
        return 0;        
    }
    public static int scanHex(byte[]bytesint pint len) {
        return scanHex(bytesplen.);
    }
    public static int scanHex(byte[]bytesint pint lenEncoding enc) {
        int v = 0;
        int c;
        while (len-- > 0 && enc.isXDigit(c = bytes[p++] & 0xff)) {
            v = (v << 4) + enc.xdigitVal(c);
        }
        return v;
    }
    public static int hexLength(byte[]bytesint pint len) {
        return hexLength(bytesplen.);
    }
    public static int hexLength(byte[]bytesint pint lenEncoding enc) {
        int hlen = 0;
        while (len-- > 0 && enc.isXDigit(bytes[p++] & 0xff)) hlen++;
        return hlen;
    }
    public static int scanOct(byte[]bytesint pint len) {
        return scanOct(bytesplen.);
    }
    public static int scanOct(byte[]bytesint pint lenEncoding enc) {
        int v = 0;
        int c;
        while (len-- > 0 && enc.isDigit(c = bytes[p++] & 0xff) && c < '8') {
            v = (v << 3) + Encoding.digitVal(c);
        }
        return v;
    }
    public static int octLength(byte[]bytesint pint len) {
        return octLength(bytesplen.);
    }
    public static int octLength(byte[]bytesint pint lenEncoding enc) {
        int olen = 0;
        int c;
        while (len-- > 0 && enc.isDigit(c = bytes[p++] & 0xff) && c < '8'olen++;
        return olen;
    }

    
Check whether input object's string value contains a null byte, and if so throw SecurityError.

Parameters:
runtime
value
    public static final void checkStringSafety(Ruby runtimeIRubyObject value) {
        RubyString s = value.asString();
        ByteList bl = s.getByteList();
        final byte[] array = bl.getUnsafeBytes();
        final int end = bl.length();
        for (int i = bl.begin(); i < end; ++i) {
            if (array[i] == (byte) 0) {
                throw runtime.newSecurityError("string contains null byte");
            }
        }
    }
    public static boolean isUnicode(Encoding enc) {
        byte[] name = enc.getName();
        return name.length > 4 && name[0] == 'U' && name[1] == 'T' && name[2] == 'F' && name[4] != '7'
    }
    public static String escapedCharFormat(int cboolean isUnicode) {
        String format;
        if (isUnicode) {
            if (c < 0x7F && Encoding.isAscii(c) && ..isPrint(c)) {
                format = "%c"
            } else if (c < 0x10000) {
                format = "\\u%04X";
            } else {
                format = "\\u{%X}";
            }
        } else {
            if (c < 0x100) {
                format = "\\x%02X";
            } else {
                format = "\\x{%X}";
            }
        }
        return format;
    }
New to GrepCode? Check out our FAQ X