1 jls.loader.provide('jls.util.StringCodec');
  2 
  3 /**
  4  * @namespace Provides utility classes for the jls language.
  5  * @name jls.util
  6  */
  7 
  8 /**
  9  * @class This class provides various String related codecs.
 10  */
 11 jls.util.StringCodec = jls.lang.Class.create({});
 12 
 13 Object.extend(jls.util.StringCodec, /** @lends jls.util.StringCodec */
 14 {
 15     /**
 16      * Encodes a specified buffer and returns the encoded base64 string.
 17      *
 18      * @param {jls.lang.ByteBuffer} buffer The buffer to encode.
 19      * @param {String} [b64pad] The padding character to use.
 20      * @returns {String} The encoded string.
 21      */
 22     base64Encode : function(buffer, b64pad) {
 23         // 64 = 2^6, 6*4 = 24, 24 = 8*3
 24         b64pad = b64pad || '=';
 25         var map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 26         var s = '';
 27         /*var logByte = function() {
 28             for (var i = 0; i < arguments.length; i++) {
 29                 var b = arguments[i];
 30                 jls.logger.info('byte: ' + b.toPaddedString(3) + ' - 0x' + b.toPaddedString(2, 16) + ' - ' + b.toPaddedString(8, 2));
 31             }
 32         };*/
 33         while (buffer.remaining() > 0) {
 34             var r = buffer.remaining();
 35             var b1 = buffer.getByte();
 36             var b2 = buffer.remaining() > 0 ? buffer.getByte() : 0;
 37             var b3 = buffer.remaining() > 0 ? buffer.getByte() : 0;
 38             //logByte(b1, b2, b3);
 39             var i1 = b1 >>> 2;
 40             var i2 =  ((b1 & 0x03) << 4) | (b2 >>> 4);
 41             var i3 =  ((b2 & 0x0f) << 2) | (b3 >>> 6);
 42             var i4 =  b3 & 0x3f;
 43             //logByte(i1, i2, i3, i4);
 44             s += map.charAt(i1) + map.charAt(i2) + (r > 1 ? map.charAt(i3) : b64pad) + (r > 2 ? map.charAt(i4) : b64pad);
 45         }
 46         return s;
 47     },
 48     base64DecodeCharCode : function(c) {
 49         if ((c >= 0x41) && (c <= 0x5a)) { // A to Z
 50             return c - 0x41;
 51         } else if ((c >= 0x61) && (c <= 0x7a)) { // a to a
 52             return c - 0x61 + 26;
 53         } else if ((c >= 0x30) && (c <= 0x39)) { // 0 to 9
 54             return c - 0x30 + 52;
 55         } else if (c == 0x2b) { // +
 56             return 62;
 57         } else if (c == 0x2f) { // slash
 58             return 63;
 59         } else if (c == 0x3d) { // =
 60             return 0;
 61         } else {
 62             throw new jls.lang.Exception('Illegal base64 character code (' + c + ', 0x' + c.toPaddedString(2, 16) + ')');
 63         }
 64     },
 65     /**
 66      * Decodes a specified base64 string and returns the decoded buffer.
 67      *
 68      * @param {String} s The string to decode.
 69      * @param {jls.lang.ByteBuffer} [buffer] The buffer to use.
 70      * @returns {jls.lang.ByteBuffer} The decoded buffer.
 71      */
 72     base64Decode : function(s, buffer) {
 73         var length = s.length;
 74         if ((length == 0) || (length % 4 != 0)) {
 75             throw new jls.lang.Exception('Invalid string length (' + length + ')');
 76         }
 77         buffer = buffer || jls.lang.ByteBuffer.allocate(length / 4 * 3);
 78         for (var i = 0; i < length; i += 4) {
 79             var c1 = s.charCodeAt(i);
 80             var c2 = s.charCodeAt(i + 1);
 81             var c3 = s.charCodeAt(i + 2);
 82             var c4 = s.charCodeAt(i + 3);
 83             var i1 = jls.util.StringCodec.base64DecodeCharCode(c1);
 84             var i2 = jls.util.StringCodec.base64DecodeCharCode(c2);
 85             var i3 = jls.util.StringCodec.base64DecodeCharCode(c3);
 86             var i4 = jls.util.StringCodec.base64DecodeCharCode(c4);
 87             var b1 = (i1 << 2) | (i2 >>> 4);
 88             var b2 = ((i2 & 0x0f) << 4) | (i3 >>> 2);
 89             var b3 = ((i3 & 0x03) << 6) | i4;
 90             buffer.putByte(b1);
 91             if (c3 == 0x3d) {
 92                 break;
 93             }
 94             buffer.putByte(b2);
 95             if (c4 == 0x3d) {
 96                 break;
 97             }
 98             buffer.putByte(b3);
 99         }
100         return buffer;
101     },
102     /**
103      * Encodes a specified buffer and returns the encoded hexadecimal string.
104      *
105      * @param {jls.lang.ByteBuffer} buffer The buffer to encode.
106      * @param {String} [b64pad] The padding character to use.
107      * @returns {String} The encoded string.
108      */
109     hexEncode : function(buffer, upperCase) {
110         var map = upperCase ? "0123456789ABCDEF" : "0123456789abcdef";
111         var s = '';
112         while (buffer.remaining() > 0) {
113             var b = buffer.getByte();
114             s += map.charAt((b >>> 4) & 0x0f) + map.charAt(b & 0x0f);
115         }
116         return s;
117     },
118     /**
119      * Decodes a specified hexadecimal string and returns the decoded buffer.
120      *
121      * @param {String} s The string to decode.
122      * @param {jls.lang.ByteBuffer} [buffer] The buffer to use.
123      * @returns {jls.lang.ByteBuffer} The decoded buffer.
124      */
125     hexDecode : function(s, buffer) {
126         var length = s.length;
127         if ((length == 0) || (length % 2 != 0)) {
128             throw new jls.lang.Exception('Invalid string length (' + length + ')');
129         }
130         buffer = buffer || jls.lang.ByteBuffer.allocate(length / 2);
131         for (var i = 0; i < length; i += 2) {
132             buffer.putByte(parseInt(s.substr(i, 2), 16));
133         }
134         return buffer;
135     }
136 });
137