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. Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2003-2004 Thomas E Enebo <enebo@acm.org> Copyright (C) 2004 Charles O Nutter <headius@headius.com> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2005 Derek Berner <derek.berner@state.nm.us> Copyright (C) 2006 Evan Buswell <ebuswell@gmail.com> Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com> Copyright (C) 2009 Joseph LaFata <joe@quibb.org> 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 org.jruby.Ruby;
  
  public class Pack {
      private static final byte[] sSp10 = "          ".getBytes();
      private static final byte[] sNil10 = "\000\000\000\000\000\000\000\000\000\000".getBytes();
      private static final int IS_STAR = -1;
      private static final ASCIIEncoding ASCII = .;
      private static final USASCIIEncoding USASCII = .;
      private static final UTF8Encoding UTF8 = .;
    
Native pack type.
  
      private static final String NATIVE_CODES = "sSiIlL";
      private static final String MAPPED_CODES = "sSiIqQ";
      
      private static final char BE = '>' - 1; // 61, only 1 char "free" b/w q and s
      private static final char LE = '<'// 60
      private static final String ENDIANESS_CODES = new String(new char[] {
              's' + 'S' + /*n*/'i' + 'I' + 'l' + 'L' + /*N*/'q' + 'Q' + ,
              's' + 'S' + /*v*/'i' + 'I' + 'l' + 'L' + /*V*/'q' + 'Q' + });
      private static final String UNPACK_IGNORE_NULL_CODES = "cC";
      private static final String PACK_IGNORE_NULL_CODES = "cCiIlLnNqQsSvV";
      private static final String PACK_IGNORE_NULL_CODES_WITH_MODIFIERS = "lLsS";
      private static final String sTooFew = "too few arguments";
      private static final byte[] hex_table;
      private static final byte[] uu_table;
      private static final byte[] b64_table;
      private static final byte[] sHexDigits;
      private static final int[] b64_xtable = new int[256];
      private static final Converter[] converters = new Converter[256];
  
      private static final BigInteger QUAD_MIN = new BigInteger("-ffffffffffffffff", 16);
      private static final BigInteger QUAD_MAX = new BigInteger("ffffffffffffffff", 16);
  
      /*
       * convert into longs, returning unsigned 64-bit values as signed longs
       * ( num2long raises a RangeError on values > Long.MAX_VALUE )
       */
      private static long num2quad(IRubyObject arg) {
          if (arg == arg.getRuntime().getNil()) {
              return 0L;
          }
          else if (arg instanceof RubyBignum) {
              BigInteger big = ((RubyBignum)arg).getValue();
             if (big.compareTo() < 0 || big.compareTo() > 0) {
                 throw arg.getRuntime().newRangeError("bignum too big to convert into `quad int'");
             }
             return big.longValue();
         }
         return RubyNumeric.num2long(arg);
     }
 
     private static long num2quad19(IRubyObject arg) {
         if (arg == arg.getRuntime().getNil()) {
             return 0L;
         }
         else if (arg instanceof RubyBignum) {
             BigInteger big = ((RubyBignum)arg).getValue();
             return big.longValue();
         }
         return RubyNumeric.num2long(arg);
     }
 
     private static float obj2flt(Ruby runtimeIRubyObject o) {
         if (o instanceof RubyStringreturn (floatstr2dbl(runtime, (RubyStringo);
 
         return (float) RubyKernel.new_float(oo).getDoubleValue();
     }
     
     private static float obj2flt19(Ruby runtimeIRubyObject o) {
         return (float) TypeConverter.toFloat(runtimeo).getDoubleValue();        
     }
     
     private static double str2dbl(Ruby runtimeRubyString o) {
         String str = o.asJavaString();
         double d = RubyNumeric.num2dbl(o.convertToFloat());
             
         if (str.matches("^\\s*[-+]?\\s*[0-9].*")) return d;
 
         throw runtime.newArgumentError("invalid value for Float");        
     }
 
     private static double obj2dbl(Ruby runtimeIRubyObject o) {
         if (o instanceof RubyStringreturn str2dbl(runtime, (RubyStringo);
 
         return RubyKernel.new_float(oo).getDoubleValue();
     }
     
     private static double obj2dbl19(Ruby runtimeIRubyObject o) {
         return TypeConverter.toFloat(runtimeo).getDoubleValue();        
     }    
 
     static {
          = ByteList.plain("0123456789ABCDEF");
          =
             ByteList.plain("`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_");
          =
             ByteList.plain("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
          = ByteList.plain("0123456789abcdef0123456789ABCDEFx");
 
         // b64_xtable for decoding Base 64
         for (int i = 0; i < 256; i++) {
             [i] = -1;
         }
         for (int i = 0; i < 64; i++) {
             [(int)[i]] = i;
         }
 
         // single precision, little-endian
         ['e'] = new Converter(4) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return RubyFloat.newFloat(runtimedecodeFloatLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeFloatLittleEndian(resultobj2flt(runtimeo));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeFloatLittleEndian(resultobj2flt19(runtimeo));
             }            
         };
         // single precision, big-endian
         ['g'] = new Converter(4) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return RubyFloat.newFloat(runtimedecodeFloatBigEndian(enc));
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeFloatBigEndian(resultobj2flt(runtimeo));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeFloatBigEndian(resultobj2flt19(runtimeo));
             }
         };
         // single precision, native
         Converter tmp = new Converter(4) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return RubyFloat.newFloat(runtime
                         . == . ? 
                         decodeFloatBigEndian(enc) : decodeFloatLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 if (. == .) {
                     encodeFloatBigEndian(resultobj2flt(runtimeo));
                 } else {
                     encodeFloatLittleEndian(resultobj2flt(runtimeo));
                 }
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result) {
                 if (. == .) {                
                     encodeFloatBigEndian(resultobj2flt19(runtimeo));
                 } else {
                     encodeFloatLittleEndian(resultobj2flt19(runtimeo));
                 }
             }
         };
         ['F'] = tmp// single precision, native
         ['f'] = tmp// single precision, native
 
         // double precision, little-endian
         ['E'] = new Converter(8) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return RubyFloat.newFloat(runtimedecodeDoubleLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeDoubleLittleEndian(resultobj2dbl(runtimeo));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeDoubleLittleEndian(resultobj2dbl19(runtimeo));
             }               
         };
         // double precision, big-endian
         ['G'] = new Converter(8) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return RubyFloat.newFloat(runtimedecodeDoubleBigEndian(enc));
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeDoubleBigEndian(resultobj2dbl(runtimeo));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeDoubleBigEndian(resultobj2dbl19(runtimeo));
             }
         };
         // double precision, native
         tmp = new Converter(8) {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 if (. == .) {
                     return RubyFloat.newFloat(runtimedecodeDoubleBigEndian(enc));
                 } else {
                     return RubyFloat.newFloat(runtimedecodeDoubleLittleEndian(enc));
                 }
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 if (. == .) {
                     encodeDoubleBigEndian(resultobj2dbl(runtimeo));
                 } else {
                     encodeDoubleLittleEndian(resultobj2dbl(runtimeo));
                 }
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeDoubleLittleEndian(resultobj2dbl19(runtimeo));
             }     
         };
         ['D'] = tmp// double precision, native
         ['d'] = tmp// double precision, native
 
         // signed short, little-endian
         tmp = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeShortUnsignedLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeShortLittleEndian(resultoverflowQuad(num2quad(o)));
             }
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeShortLittleEndian(resultoverflowQuad(num2quad19(o)));
             }            
         };
         ['v'] = tmp;
         ['S' + ] = tmp;
         // signed short, big-endian
         tmp = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeShortUnsignedBigEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortBigEndian(resultoverflowQuad(num2quad(o)));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortBigEndian(resultoverflowQuad(num2quad19(o)));
             }
         };
         ['n'] = tmp;
         ['S' + ] = tmp;
         // signed short, native
         ['s'] = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(. == . ? 
                         decodeShortBigEndian(enc) : decodeShortLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortByByteOrder(resultoverflowQuad(num2quad(o))); // XXX: 0xffff0000 on BE?
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortByByteOrder(resultoverflowQuad(num2quad19(o))); // XXX: 0xffff0000 on BE?
             }
         };
         // unsigned short, native
         ['S'] = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(. == . ?
                     decodeShortUnsignedBigEndian(enc) : decodeShortUnsignedLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeShortByByteOrder(resultoverflowQuad(num2quad(o)));
             }
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeShortByByteOrder(resultoverflowQuad(num2quad19(o)));
             }
         };
         // signed short, little endian
         ['s' + ] = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeShortLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortLittleEndian(resultoverflowQuad(num2quad(o))); // XXX: 0xffff0000 on BE?
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortLittleEndian(resultoverflowQuad(num2quad19(o))); // XXX: 0xffff0000 on BE?
             }
         };
         // signed short, big endian
         ['s' + ] = new QuadConverter(2, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeShortBigEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortBigEndian(resultoverflowQuad(num2quad(o))); // XXX: 0xffff0000 on BE?
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result) {
                 encodeShortBigEndian(resultoverflowQuad(num2quad19(o))); // XXX: 0xffff0000 on BE?
             }
         };
 
         // signed char
         ['c'] = new Converter(1, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 int c = enc.get();
                 return runtime.newFixnum(c > (char) 127 ? c-256 : c);
             }
             public void encode(Ruby runtimeIRubyObject oByteList result) {
                 byte c = (byte) (RubyNumeric.num2long(o) & 0xff);
                 result.append(c);
             }
         };
         // unsigned char
         ['C'] = new Converter(1, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(enc.get() & 0xFF);
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 byte c = o == runtime.getNil() ? 0 : (byte) (RubyNumeric.num2long(o) & 0xff);
                 result.append(c);
             }
         };
 
         // unsigned long, little-endian
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeIntUnsignedLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeIntLittleEndian(result, (int) RubyNumeric.num2long(o));
             }
         };
         ['V'] = tmp;
         ['L' + ] = tmp;
         ['I' + ] = tmp;
         
         // unsigned long, big-endian
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeIntUnsignedBigEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeIntBigEndian(result, (int) RubyNumeric.num2long(o));
             }
         };
         ['N'] = tmp;
         ['L' + ] = tmp;
         ['I' + ] = tmp;
 
         // unsigned int, native
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 if (. == .) {
                     return runtime.newFixnum(decodeIntUnsignedBigEndian(enc));
                 } else {
                     return runtime.newFixnum(decodeIntUnsignedLittleEndian(enc));
                 }
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 int s = o == runtime.getNil() ? 0 : (int) RubyNumeric.num2long(o);
                 packInt_i(results);
             }
         };
         ['I'] = tmp// unsigned int, native
         ['L'] = tmp// unsigned long, native
 
         // int, native
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 int value = unpackInt_i(enc);
                 return runtime.newFixnum(value);
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 int s = o == runtime.getNil() ? 0 : (int)RubyNumeric.num2long(o);
                 packInt_i(results);
             }
         };
         ['i'] = tmp// int, native
         ['l'] = tmp// long, native
         
         // int, little endian
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeIntLittleEndian(enc));
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 int s = o == runtime.getNil() ? 0 : (int)RubyNumeric.num2long(o);
                 encodeIntLittleEndian(results);
             }
         };
         ['i' + ] = tmp// int, native
         ['l' + ] = tmp// long, native
         
         // int, big endian
         tmp = new Converter(4, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeIntBigEndian(enc));
             }
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 int s = o == runtime.getNil() ? 0 : (int)RubyNumeric.num2long(o);
                 encodeIntBigEndian(results);
             }
         };
         ['i' + ] = tmp// int, native
         ['l' + ] = tmp// long, native
 
         // 64-bit number, native (as bignum)
         ['Q'] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 long l = . == . ? decodeLongBigEndian(enc) : decodeLongLittleEndian(enc);
 
                 return RubyBignum.bignorm(runtime,BigInteger.valueOf(l).and(new BigInteger("FFFFFFFFFFFFFFFF", 16)));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongByByteOrder(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongByByteOrder(resultnum2quad19(o));
             }
         };
         // 64-bit number, little endian (as bignum)
         ['Q' + ] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 long l = decodeLongLittleEndian(enc);
                 return RubyBignum.bignorm(runtime,BigInteger.valueOf(l).and(new BigInteger("FFFFFFFFFFFFFFFF", 16)));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongLittleEndian(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongLittleEndian(resultnum2quad19(o));
             }
         };
         // 64-bit number, big endian (as bignum)
         ['Q' + ] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 long l = decodeLongBigEndian(enc);
                 return RubyBignum.bignorm(runtime,BigInteger.valueOf(l).and(new BigInteger("FFFFFFFFFFFFFFFF", 16)));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongBigEndian(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongBigEndian(resultnum2quad19(o));
             }
         };
         // 64-bit number, native (as fixnum)
         ['q'] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(. == . ? 
                         decodeLongBigEndian(enc) : decodeLongLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongByByteOrder(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongByByteOrder(resultnum2quad19(o));
             }
         };
         // 64-bit number, little-endian (as fixnum)
         ['q' + ] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeLongLittleEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongLittleEndian(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongLittleEndian(resultnum2quad19(o));
             }
         };
         // 64-bit number, big-endian (as fixnum)
         ['q' + ] = new QuadConverter(8, "Integer") {
             public IRubyObject decode(Ruby runtimeByteBuffer enc) {
                 return runtime.newFixnum(decodeLongBigEndian(enc));
             }
             
             public void encode(Ruby runtimeIRubyObject oByteList result){
                 encodeLongBigEndian(resultnum2quad(o));
             }
             
             @Override
             public void encode19(Ruby runtimeIRubyObject oByteList result){
                 encodeLongBigEndian(resultnum2quad19(o));
             }
         };
     }
 
     public static int unpackInt_i(ByteBuffer enc) {
         int value;
         if (. == .) {
             value = decodeIntBigEndian(enc);
         } else {
             value = decodeIntLittleEndian(enc);
         }
         return value;
     }
 
     public static ByteList packInt_i(ByteList resultint s) {
         if (. == .) {
             encodeIntBigEndian(results);
         } else {
             encodeIntLittleEndian(results);
         }
         return result;
     }

    
encodes a String in base64 or its uuencode variant. appends the result of the encoding in a StringBuffer

Parameters:
io2Append The StringBuffer which should receive the result
i2Encode The String to encode
iLength The max number of characters to encode
iType the type of encoding required (this is the same type as used by the pack method)
tailLf true if the traililng "\n" is needed
Returns:
the io2Append buffer
 
     private static ByteList encodes(Ruby runtimeByteList io2Append,byte[]charsToEncodeint startIndexint lengthint charCountbyte encodingTypeboolean tailLf) {
         charCount = charCount < length ? charCount : length;
 
         io2Append.ensure(charCount * 4 / 3 + 6);
         int i = startIndex;
         byte[] lTranslationTable = encodingType == 'u' ?  : ;
         byte lPadding;
         if (encodingType == 'u') {
             if (charCount >= lTranslationTable.length) {
                 throw runtime.newArgumentError(
                     ""
                         + charCount
                         + " is not a correct value for the number of bytes per line in a u directive.  Correct values range from 0 to "
                         + lTranslationTable.length);
             }
             io2Append.append(lTranslationTable[charCount]);
             lPadding = '`';
         } else {
             lPadding = '=';
         }
         while (charCount >= 3) {
             byte lCurChar = charsToEncode[i++];
             byte lNextChar = charsToEncode[i++];
             byte lNextNextChar = charsToEncode[i++];
             io2Append.append(lTranslationTable[077 & (lCurChar >>> 2)]);
             io2Append.append(lTranslationTable[077 & (((lCurChar << 4) & 060) | ((lNextChar >>> 4) & 017))]);
             io2Append.append(lTranslationTable[077 & (((lNextChar << 2) & 074) | ((lNextNextChar >>> 6) & 03))]);
             io2Append.append(lTranslationTable[077 & lNextNextChar]);
             charCount -= 3;
         }
         if (charCount == 2) {
             byte lCurChar = charsToEncode[i++];
             byte lNextChar = charsToEncode[i++];
             io2Append.append(lTranslationTable[077 & (lCurChar >>> 2)]);
             io2Append.append(lTranslationTable[077 & (((lCurChar << 4) & 060) | ((lNextChar >> 4) & 017))]);
             io2Append.append(lTranslationTable[077 & (((lNextChar << 2) & 074) | (('\0' >> 6) & 03))]);
             io2Append.append(lPadding);
         } else if (charCount == 1) {
             byte lCurChar = charsToEncode[i++];
             io2Append.append(lTranslationTable[077 & (lCurChar >>> 2)]);
             io2Append.append(lTranslationTable[077 & (((lCurChar << 4) & 060) | (('\0' >>> 4) & 017))]);
             io2Append.append(lPadding);
             io2Append.append(lPadding);
         }
         if (tailLf) {
             io2Append.append('\n');
         }
         return io2Append;
     }

    
encodes a String with the Quoted printable, MIME encoding (see RFC2045). appends the result of the encoding in a StringBuffer

Parameters:
io2Append The StringBuffer which should receive the result
i2Encode The String to encode
iLength The max number of characters to encode
Returns:
the io2Append buffer
 
     private static ByteList qpencode(ByteList io2AppendByteList i2Encodeint iLength) {
         io2Append.ensure(1024);
         int lCurLineLength = 0;
         int lPrevChar = -1;
         byte[] l2Encode = i2Encode.getUnsafeBytes();
         try {
             int end = i2Encode.getBegin() + i2Encode.getRealSize();
             for (int i = i2Encode.getBegin(); i < endi++) {
                 int lCurChar = l2Encode[i] & 0xff;
                 if (lCurChar > 126 || (lCurChar < 32 && lCurChar != '\n' && lCurChar != '\t') || lCurChar == '=') {
                     io2Append.append('=');
                     io2Append.append([lCurChar >>> 4]);
                     io2Append.append([lCurChar & 0x0f]);
                     lCurLineLength += 3;
                     lPrevChar = -1;
                 } else if (lCurChar == '\n') {
                     if (lPrevChar == ' ' || lPrevChar == '\t') {
                         io2Append.append('=');
                         io2Append.append(lCurChar);
                     }
                     io2Append.append(lCurChar);
                     lCurLineLength = 0;
                     lPrevChar = lCurChar;
                 } else {
                     io2Append.append(lCurChar);
                     lCurLineLength++;
                     lPrevChar = lCurChar;
                 }
                 if (lCurLineLength > iLength) {
                     io2Append.append('=');
                     io2Append.append('\n');
                     lCurLineLength = 0;
                     lPrevChar = '\n';
                 }
             }
         } catch (ArrayIndexOutOfBoundsException e) {
             //normal exit, this should be faster than a test at each iterations for string with more than
             //about 40 char
         }
 
         if (lCurLineLength > 0) {
             io2Append.append('=');
             io2Append.append('\n');
         }
         return io2Append;
     }

    
Decodes str (which may contain binary data) according to the format string, returning an array of each value extracted. The format string consists of a sequence of single-character directives.
Each directive may be followed by a number, indicating the number of times to repeat with this directive. An asterisk (``*'') will use up all remaining elements.
The directives sSiIlL may each be followed by an underscore (``_'') to use the underlying platform's native size for the specified type; otherwise, it uses a platform-independent consistent size.
Spaces are ignored in the format string.

See also:
org.jruby.RubyArray.pack(org.jruby.runtime.ThreadContext,org.jruby.runtime.builtin.IRubyObject)

Directives for String.unpack
Format Function Returns
AString with trailing nulls and spaces removed.String
aString.String
BExtract bits from each character (msb first).String
bExtract bits from each character (lsb first).String
CExtract a character as an unsigned integer.Fixnum
cExtract a character as an integer.Fixnum
dTreat sizeof(double) characters as a native double.Float
ETreat sizeof(double) characters as a double in little-endian byte order.Float
eTreat sizeof(float) characters as a float in little-endian byte order.Float
fTreat sizeof(float) characters as a native float.Float
GTreat sizeof(double) characters as a double in network byte order.Float
gTreat sizeof(float) characters as a float in network byte order.Float
HExtract hex nibbles from each character (most significant first).String
hExtract hex nibbles from each character (least significant first).String
ITreat sizeof(int) 1 successive characters as an unsigned native integer.Integer
iTreat sizeof(int) 1 successive characters as a signed native integer.Integer
LTreat four1 successive characters as an unsigned native long integer.Integer
lTreat four1 successive characters as a signed native long integer.Integer
MExtract a quoted-printable string.String
mExtract a base64 encoded string.String
NTreat four characters as an unsigned long in network byte order.Fixnum
nTreat two characters as an unsigned short in network byte order.Fixnum
PTreat sizeof(char *) characters as a pointer, and return len characters from the referenced location.String
pTreat sizeof(char *) characters as a pointer to a null-terminated string.String
STreat two1 successive characters as an unsigned short in native byte order.Fixnum
sTreat two1 successive characters as a signed short in native byte order.Fixnum
UExtract UTF-8 characters as unsigned integers.Integer
uExtract a UU-encoded string.String
VTreat four characters as an unsigned long in little-endian byte order.Fixnum
vTreat two characters as an unsigned short in little-endian byte order.Fixnum
XSkip backward one character.---
xSkip forward one character.---
ZString with trailing nulls removed.String
@Skip to the offset given by the length argument.---

1 May be modified by appending ``_'' to the directive.

 
     public static RubyArray unpack(Ruby runtimeByteList encodedStringByteList formatString) {
         Encoding encoding = encodedString.getEncoding();
         RubyArray result = runtime.newArray();
         // FIXME: potentially could just use ByteList here?
         ByteBuffer format = ByteBuffer.wrap(formatString.getUnsafeBytes(), formatString.begin(), formatString.length());
         ByteBuffer encode = ByteBuffer.wrap(encodedString.getUnsafeBytes(), encodedString.begin(), encodedString.length());
         int type = 0;
         int next = safeGet(format);
 
         while (next != 0) {
             type = next;
             next = safeGet(format);
             if (.indexOf(type) != -1 && next == 0) {
                 next = safeGetIgnoreNull(format);
             }
 
             // Next indicates to decode using native encoding format
             if (next == '_' || next == '!') {
                 int index = .indexOf(type);
                 if (index == -1) {
                     throw runtime.newArgumentError("'" + next +
                             "' allowed only after types " + );
                 }
                 type = .charAt(index);
                 
                 next = safeGet(format);
             }
             
             if (next == '>' || next == '<') {
                 next = next == '>' ?  : ;
                 int index = .indexOf(type + next);
                 if (index == -1) {
                     throw runtime.newArgumentError("'" + (char)next +
                             "' allowed only after types sSiIlLqQ");
                 }
                 type = .charAt(index);
                 next = safeGet(format);
             }
 
             // How many occurrences of 'type' we want
             int occurrences = 0;
             if (next == 0) {
                 occurrences = 1;
             } else {
                 if (next == '*') {
                     occurrences = ;
                     next = safeGet(format);
                 } else if (.isDigit(next)) {
                     occurrences = 0;
                     do {
                         occurrences = occurrences * 10 + Character.digit((char)(next & 0xFF), 10);
                         next = safeGet(format);
                     } while (next != 0 && .isDigit(next));
                 } else {
                     occurrences = type == '@' ? 0 : 1;
                 }
             }
            // See if we have a converter for the job...
            Converter converter = [type];
            if (converter != null) {
                decode(runtimeencodeoccurrencesresultconverter);
                type = next;
                continue;
            }
            // Otherwise the unpack should be here...
            switch (type) {
                case '@' :
                    try {
                        if (occurrences == ) {
                            encode.position(encodedString.begin() + encode.remaining());
                        } else {
                            encode.position(encodedString.begin() + occurrences);
                        }
                    } catch (IllegalArgumentException iae) {
                        throw runtime.newArgumentError("@ outside of string");
                    }
                    break;
                case '%' :
                    throw runtime.newArgumentError("% is not supported");
                case 'A' :
                    {
                    if (occurrences ==  || occurrences > encode.remaining()) {
                        occurrences = encode.remaining();
                    }
                    byte[] potential = new byte[occurrences];
                    encode.get(potential);
                    for (int t = occurrences - 1; occurrences > 0; occurrences--, t--) {
                        byte c = potential[t];
                           if (c != '\0' && c != ' ') {
                               break;
                           }
                    }
                    result.append(RubyString.newString(runtimenew ByteList(potential, 0, occurrencesencodingfalse)));
                    }
                    break;
                case 'Z' :
                    {
                        boolean isStar = (occurrences == );
                        if (occurrences ==  || occurrences > encode.remaining()) {
                            occurrences = encode.remaining();
                        }
                        byte[] potential = new byte[occurrences];
                        int t = 0;
                        while (t < occurrences) {
                            byte b = encode.get();
                            if (b == 0) {
                                break;
                            }
                            potential[t] = b
                            t++;
                        }
                        result.append(RubyString.newString(runtimenew ByteList(potential, 0, tencodingfalse)));
                        // In case when the number of occurences is
                        // explicitly specified, we have to read up
                        // the remaining garbage after the '\0' to
                        // satisfy the requested pattern.
                        if (!isStar) {
                            if (t < occurrences) {
                                // We encountered '\0' when
                                // were reading the buffer above,
                                // increment the number of read bytes.
                                t++;
                            }
                            while (t < occurrences) {
                                encode.get();
                                t++;
                            }
                        }
                    }
                    break;
                case 'a' :
                    if (occurrences ==  || occurrences > encode.remaining()) {
                        occurrences = encode.remaining();
                    }
                    byte[] potential = new byte[occurrences];
                    encode.get(potential);
                    result.append(RubyString.newString(runtimenew ByteList(potentialencodingfalse)));
                    break;
                case 'b' :
                    {
                        if (occurrences ==  || occurrences > encode.remaining() * 8) {
                            occurrences = encode.remaining() * 8;
                        }
                        int bits = 0;
                        byte[] lElem = new byte[occurrences];
                        for (int lCurByte = 0; lCurByte < occurrenceslCurByte++) {
                            if ((lCurByte & 7) != 0) {
                                bits >>>= 1;
                            } else {
                                bits = encode.get();
                            }
                            lElem[lCurByte] = (bits & 1) != 0 ? (byte)'1' : (byte)'0';
                        }
                        result.append(RubyString.newString(runtimenew ByteList(lElemencodingfalse)));
                    }
                    break;
                case 'B' :
                    {
                        if (occurrences ==  || occurrences > encode.remaining() * 8) {
                            occurrences = encode.remaining() * 8;
                        }
                        int bits = 0;
                        byte[] lElem = new byte[occurrences];
                        for (int lCurByte = 0; lCurByte < occurrenceslCurByte++) {
                            if ((lCurByte & 7) != 0) {
                                bits <<= 1;
                            } else {
                                bits = encode.get();
                            }
                            lElem[lCurByte] = (bits & 128) != 0 ? (byte)'1' : (byte)'0';
                        }
                        result.append(RubyString.newString(runtimenew ByteList(lElemencodingfalse)));
                    }
                    break;
                case 'h' :
                    {
                        if (occurrences ==  || occurrences > encode.remaining() * 2) {
                            occurrences = encode.remaining() * 2;
                        }
                        int bits = 0;
                        byte[] lElem = new byte[occurrences];
                        for (int lCurByte = 0; lCurByte < occurrenceslCurByte++) {
                            if ((lCurByte & 1) != 0) {
                                bits >>>= 4;
                            } else {
                                bits = encode.get();
                            }
                            lElem[lCurByte] = [bits & 15];
                        }
                        result.append(RubyString.newString(runtimenew ByteList(lElemencodingfalse)));
                    }
                    break;
                case 'H' :
                    {
                        if (occurrences ==  || occurrences > encode.remaining() * 2) {
                            occurrences = encode.remaining() * 2;
                        }
                        int bits = 0;
                        byte[] lElem = new byte[occurrences];
                        for (int lCurByte = 0; lCurByte < occurrenceslCurByte++) {
                            if ((lCurByte & 1) != 0) {
                                bits <<= 4;
                            } else {
                                bits = encode.get();
                            }
                            lElem[lCurByte] = [(bits >>> 4) & 15];
                        }
                        result.append(RubyString.newString(runtimenew ByteList(lElemencodingfalse)));
                    }
                    break;
                case 'u':
                {
                    int length = encode.remaining() * 3 / 4;
                    byte[] lElem = new byte[length];
                    int index = 0;
                    int s = 0;
                    int total = 0;
                    if (length > 0) s = encode.get();
                    while (encode.hasRemaining() && s > ' ' && s < 'a') {
                        int abcd;
                        byte[] hunk = new byte[3];
                        int len = (s - ' ') & 077;
                        s = safeGet(encode);
                        total += len;
                        if (total > length) {
                            len -= total - length;
                            total = length;
                        }
                        while (len > 0) {
                            int mlen = len > 3 ? 3 : len;
                            if (encode.hasRemaining() && s >= ' ') {
                                a = (s - ' ') & 077;
                                s = safeGet(encode);
                            } else
                                a = 0;
                            if (encode.hasRemaining() && s >= ' ') {
                                b = (s - ' ') & 077;
                                s = safeGet(encode);
                            } else
                            &nb