/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * 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.
 *
 * The Original Code is JIM.
 *
 * The Initial Developer of the Original Code is
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * crypto.Utils
 *
 *
 */
function swapWords(data) {
    var i, v;

    for (i=0; i < data.length; i++) {
        v = data[i];
        data[i] = ((v>>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v<<24)&0xff000000);
    }
    return data;
}

function string2bin(data, swapped, isWideChar) {
    if (swapped)
        if (isWideChar)
            return swappedWideString2bin(data);
        else
            return swappedNarrowString2bin(data);
    else
        if (isWideChar)
            return wideString2bin(data);
        else
            return narrowString2bin(data);
}

function swappedNarrowString2bin(data) {
    var ret = new Array(data.length>>2);
    var i;

    for (i = 0; i < data.length; i+=4)
        ret[i>>2] = ((data.charCodeAt(i) & 0xff) << 24) |
            ((data.charCodeAt(i+1) & 0xff) << 16) |
            ((data.charCodeAt(i+2) & 0xff) << 8) |
            (data.charCodeAt(i+3) & 0xff);
    for (; i < data.length; i++)
        ret[i>>2] |= (data.charCodeAt(i) & 0xff) << ((i%4)<<3);
    return ret;
}

function narrowString2bin(data) {
    var ret = new Array(data.length>>2);
    var i;

    for (i = 0; i <data.length; i+=4)
        ret[i>>2] = ((data.charCodeAt(i+3) & 0xff) << 24) |
            ((data.charCodeAt(i+2) & 0xff) << 16) |
            ((data.charCodeAt(i+1) & 0xff) << 8) |
            (data.charCodeAt(i) & 0xff);
    for (; i <data.length; i++)
        ret[i>>2] |= (data.charCodeAt(i) & 0xff) << ((3-i%4)<<3);
    return ret;
}

function swappedWideString2bin(data) {
    var ret = new Array(data.length>>2);
    var i;

    for (i = 0; i <data.length; i+=2)
        ret[i>>1] = ((data.charCodeAt(i) & 0xffff) << 16) |
            (data.charCodeAt(i+1) & 0xff);
    for (; i <data.length; i++)
        ret[i>>1] |= (data.charCodeAt(i) & 0xffff) << ((i%2)<<4);
    return ret;
}

function wideString2bin(data) {
    var ret = new Array(data.length>>2);
    var i;

    for (i = 0; i <data.length; i+=2)
        ret[i>>1] = ((data.charCodeAt(i+1) & 0xffff) << 16) |
            (data.charCodeAt(i) & 0xff);
    for (; i <data.length; i++)
        ret[i>>1] |= (data.charCodeAt(i) & 0xffff) << ((1-i%2)<<4);
    return ret;
}

function bin2string(data, isWideChar) {
    var ret = new String();
    var bytes = isWideChar ? 2 : 4;
    var mask = (1 << ((6-bytes)*4)) - 1;
    var byteshift = bytes>>1;
    var i;

    for (i = 0; i <data.length*bytes; i++)
        ret += String.fromCharCode((data[i>>byteshift]>>((i%bytes)*8))&mask);
    return ret;
}

function bin2hex(data) {
    var hexchars = "0123456789abcdef";
    var i;
    var ret = "";

    for (i = 0; i < data.length; i++) {
        ret+=
            hexchars.charAt((data[i]>>4)&0xf)+hexchars.charAt(data[i]&0xf)+
            hexchars.charAt((data[i]>>12)&0xf)+hexchars.charAt((data[i]>>8)&0xf)+
            hexchars.charAt((data[i]>>20)&0xf)+hexchars.charAt((data[i]>>16)&0xf)+
            hexchars.charAt((data[i]>>28)&0xf)+hexchars.charAt((data[i]>>24)&0xf);
    }
    return ret;
}

function bin2base64(data, padchar) {
    var base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var i, val;
    var ret = "";

    for (i = 0; i < data.length*4; i+=3) {
        val = (data[i>>2] >> (8*(i%4)) & 0xff) << 16 |
            (data[(i+1)>>2] >> (8*((i+1)%4)) & 0xff) << 8 |
            (data[(i+2)>>2] >> (8*((i+2)%4)) & 0xff);
        ret+=base64chars.charAt(val>>18) + base64chars.charAt((val>>12) & 0x3f);
        ret+=(i+2 > data.length*4) ? padchar : base64chars.charAt((val>>6) & 0x3f);
        ret+=(i+3 > data.length*4) ? padchar : base64chars.charAt(val & 0x3f);
    }
    return ret;
}

function madd(x, y) {
    return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}

function bitroll(x, r) {
    return (x << r) | (x >>> (32-r));
}
