view dcrypt/misc/ByteConverter.d @ 23:4589f8c5eb3c

Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
author Thomas Dixon <reikon@reikon.us>
date Sat, 14 Feb 2009 19:58:20 -0500
parents
children 6428dfd7fede
line wrap: on
line source

/**
 * This file is part of the dcrypt project.
 *
 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
 * License:   MIT
 * Authors:   Thomas Dixon
 */

module dcrypt.misc.ByteConverter;

/** Converts between integral types and unsigned byte arrays */
struct ByteConverter {
    private static const char[] hexits = "0123456789abcdef";
    
    /** Conversions between little endian integrals and bytes */
    struct LittleEndian {
        /**
         * Converts the supplied array to integral type T
         * 
         * Params:
         *     x_ = The supplied array of bytes (ubytes, bytes, chars, whatever)
         * 
         * Returns:
         *     A integral of type T created with the supplied bytes placed
         *     in the specified byte order.
         */
        static T to(T)(void[] x_) {
            ubyte[] x = cast(ubyte[])x_;
            
            T result = ((x[0] & 0xff)       |
                       ((x[1] & 0xff) << 8));
                       
            static if (T.sizeof >= int.sizeof) {
                result |= ((x[2] & 0xff) << 16) |
                          ((x[3] & 0xff) << 24);
            }
            
            static if (T.sizeof >= long.sizeof) {
                result |= (cast(T)(x[4] & 0xff) << 32) |
                          (cast(T)(x[5] & 0xff) << 40) |
                          (cast(T)(x[6] & 0xff) << 48) |
                          (cast(T)(x[7] & 0xff) << 56);
            }
            
            return result;
        }
        
        /**
         * Converts the supplied integral to an array of unsigned bytes.
         * 
         * Params:
         *     input = Integral to convert to bytes
         * 
         * Returns:
         *     Integral input of type T split into its respective bytes
         *     with the bytes placed in the specified byte order.
         */
        static ubyte[] from(T)(T input) {
            ubyte[] output = new ubyte[T.sizeof];
            
            output[0] = cast(ubyte)(input);
            output[1] = cast(ubyte)(input >> 8);
            
            static if (T.sizeof >= int.sizeof) {
                output[2] = cast(ubyte)(input >> 16);
                output[3] = cast(ubyte)(input >> 24);
            }
            
            static if (T.sizeof >= long.sizeof) {
                output[4] = cast(ubyte)(input >> 32);
                output[5] = cast(ubyte)(input >> 40);
                output[6] = cast(ubyte)(input >> 48);
                output[7] = cast(ubyte)(input >> 56);
            }
            
            return output;
        }
    }
    
    /** Conversions between big endian integrals and bytes */
    struct BigEndian {
        
        static T to(T)(void[] x_) {
            ubyte[] x = cast(ubyte[])x_;
            
            static if (is(T == ushort) || is(T == short)) {
                return cast(T) (((x[0] & 0xff) << 8) |
                                 (x[1] & 0xff));
            } else static if (is(T == uint) || is(T == int)) {
                return cast(T) (((x[0] & 0xff) << 24) |
                                ((x[1] & 0xff) << 16) |
                                ((x[2] & 0xff) << 8)  |
                                 (x[3] & 0xff));
            } else static if (is(T == ulong) || is(T == long)) {
                return cast(T) ((cast(T)(x[0] & 0xff) << 56) |
                                (cast(T)(x[1] & 0xff) << 48) |
                                (cast(T)(x[2] & 0xff) << 40) |
                                (cast(T)(x[3] & 0xff) << 32) |
                                ((x[4] & 0xff) << 24) |
                                ((x[5] & 0xff) << 16) |
                                ((x[6] & 0xff) << 8)  |
                                 (x[7] & 0xff));
            }
        }
        
        static ubyte[] from(T)(T input) {
            ubyte[] output = new ubyte[T.sizeof];
            
            static if (T.sizeof == long.sizeof) {
                output[0] = cast(ubyte)(input >> 56);
                output[1] = cast(ubyte)(input >> 48);
                output[2] = cast(ubyte)(input >> 40);
                output[3] = cast(ubyte)(input >> 32);
                output[4] = cast(ubyte)(input >> 24);
                output[5] = cast(ubyte)(input >> 16);
                output[6] = cast(ubyte)(input >> 8);
                output[7] = cast(ubyte)(input);
            } else static if (T.sizeof == int.sizeof) {
                output[0] = cast(ubyte)(input >> 24);
                output[1] = cast(ubyte)(input >> 16);
                output[2] = cast(ubyte)(input >> 8);
                output[3] = cast(ubyte)(input);
            } else static if (T.sizeof == short.sizeof) {
                output[0] = cast(ubyte)(input >> 8);
                output[1] = cast(ubyte)(input);
            }
            return output;
        }
    }

    static char[] hexEncode(void[] input_) {
        ubyte[] input = cast(ubyte[])input_;
        char[] output = new char[input.length<<1];
        
        int i = 0;
        foreach (ubyte j; input) { 
            output[i++] = hexits[j>>4];
            output[i++] = hexits[j&0xf];
        }
        return output;    
    }
    
    static ubyte[] hexDecode(char[] input) {
        ubyte[] output = new ubyte[input.length>>1];
        
        static ubyte[char] hexitIndex;
        for (int i = 0; i < hexits.length; i++)
            hexitIndex[hexits[i]] = i;
            
        for (int i = 0, j = 0; i < output.length; i++) {
            output[i] = hexitIndex[input[j++]] << 4;
            output[i] |= hexitIndex[input[j++]]; 
        }
        return output;
    }
}