summaryrefslogblamecommitdiffstats
path: root/src/net/gcdc/asn1/uper/ByteBitBuffer.java
blob: e55d9d5011e2560712a1cff0e8038e4bf5b8469d (plain) (tree)














































































































































































































































































                                                                                                   
package net.gcdc.asn1.uper;



public class ByteBitBuffer implements BitBuffer {

    byte[] bytes;
    byte[] mask = new byte[] {
     (byte) 0b1000_0000,
            0b0100_0000,
            0b0010_0000,
            0b0001_0000,
            0b0000_1000,
            0b0000_0100,
            0b0000_0010,
            0b0000_0001,
    };

    boolean isFinite;

    int mark;
    int position;
    int limit;

    
    @Override public boolean get(int index) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("Index " + index + " is less than 0");
        } else if (index >= limit) {
            throw new IndexOutOfBoundsException("Index " + index + " violates the limit " + limit);
        }
        boolean result = (bytes[index / 8] & mask[index % 8]) != 0;
        return result;
    }

    @Override public boolean get() {
        boolean result = get(position);
        position++;
        return result;
    }

    private void grow() {
        byte[] newbytes = new byte[2 * bytes.length];
        System.arraycopy(bytes, 0, newbytes, 0, bytes.length);
        bytes = newbytes;
    }

    @Override public BitBuffer put(int index, boolean element) {
        if (bytes.length <= index / 8) {
            if (isFinite) { throw new IndexOutOfBoundsException(); }
            else { grow(); }
        }
        if (element) {
            bytes[index / 8] |= mask[index % 8];
        } else {
            bytes[index / 8] &= ~mask[index % 8];
        }
        return this;
    }

    @Override public BitBuffer put(boolean element) {
        put(position, element);
        position++;
        limit = limit < position ? position : limit;  // TODO: should it be here?
        return this;
    }

    @Override public BitBuffer putByte(byte element) {
        for (int i = 0; i < 8; i++) {
            put((element & mask[i]) != 0);
        }
        return this;
    }
    
    @Override public BitBuffer putByteArray(int index, byte[] data) {
    	
    	for (int l = 0; l < data.length;l++) {
    		for (int i = 0; i < 8; i++) {
    			put((data[l] & mask[i]) != 0);
    		}
    	}	
    	return this;
    }
    

    @Override public byte getByte() {
        byte result = 0;
        for (int i = 0; i < 8; i++) {
            result |= (get() ? 1 : 0) << (7 - i);
        }
        return result;
    }

    @Override public int limit() {
        return limit;
    }

    @Override public String toBooleanString(int startIndex, int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = startIndex; i < startIndex + length; i++) {
            sb.append(get(i) ? "1" : "0");
        }
        return sb.toString();
    }

    @Override public int capacity() {
        return isFinite ? bytes.length * 8 : Integer.MAX_VALUE;
    }

    @Override public int position() {
        return position;
    }

    @Override public int remaining() {
        return limit - position;
    }

    public ByteBitBuffer(byte[] backingArray) {
        this.bytes = backingArray;
        this.isFinite = true;
    }

    private ByteBitBuffer(int initialCapacity) {
        this.bytes = new byte[initialCapacity];
        this.isFinite = false;
    }

    public static ByteBitBuffer allocate(int lengthInBits) {
        return new ByteBitBuffer(new byte[(lengthInBits + 7) / 8]);
    }

    public static ByteBitBuffer createInfinite() {
        return new ByteBitBuffer(64);
    }

    @Override public BitBuffer flip() {
        limit = position;
        position = 0;
        return this;
    }

    @Override public String toBooleanStringFromPosition(int startIndex) {
        return toBooleanString(startIndex, position-startIndex);
    }

    @Override public byte[] array() {
        return bytes;
    }

	@Override
	public void putInteger(int position, int length,int number) {
		String s = Integer.toBinaryString(number);
		if (s.length() > length) {
			//value is to large
			return;
		}
		
		for (int i = 0;i < length;i++){
			int index = position + i;
     	    this.put(index,false);
		}
		
		
		int startIndex = position + length - s.length();
		for (int i = 0;i < s.length();i++){
			/*
			 * i = max --> index = position + length - 1
			 * i = 0 --> index = position + 
			 */
			int index = startIndex + i;
			if (s.charAt(i) == '1') {
			  this.put(index, true );
			} else {
			  this.put(index, false);		
			}
		}
		
	}
	
	@Override
	public void putChar5String(int position, int length, String s) {

		String upperCaseString  = s.toUpperCase();
		int offset = 0;
		for (int i = 0; i < s.length() ; i++) {
			char character = upperCaseString.charAt(i);
			int intValue = (int) character - 32;
			if (intValue > -1 && intValue < 64) {
				this.putInteger(position + offset,5, intValue); 
				offset = offset + 5;
			} else {
				this.putInteger(position + offset,5,0); 
				position = position + 5;
			}
		}
	}

	@Override
	public void putChar6String(int position, int length, String s) {

		String upperCaseString  = s.toUpperCase();
		int offset = 0;
		for (int i = 0; i < s.length() ; i++) {
			char character = upperCaseString.charAt(i);
			int intValue = (int) character - 32;
			if (intValue > -1 && intValue < 64) {
				this.putInteger(position + offset,6, intValue); 
				offset = offset + 6;
			} else {
				this.putInteger(position + offset,6,0); 
				position = position + 6;
			}
		}
	}

	@Override
	public int getInteger(int position, int length) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0;i < length;i++){
			if (this.get(position + i)) {
				sb.append("1");
			} else {
				sb.append("0");
			}
		}
	    return Integer.parseInt(sb.toString(), 2);
	}

	@Override
	public String getChar6String(int position, int length) {
		
		StringBuilder stringBuilder = new StringBuilder();

		int chars = length / 6;

		for (int i = 0; i < chars; i++) {
			int newPosition =  position + i * 6;

			int x =  this.getInteger(newPosition, 6);
			x = x + 32;
		
			char c = (char) x;
			stringBuilder.append(c);

		}

		return stringBuilder.toString().trim();
	}
	
	@Override
	public String getChar5String(int position, int length) {
		
		StringBuilder stringBuilder = new StringBuilder();

		int chars = length / 5;

		for (int i = 0; i < chars; i++) {
			int newPosition =  position + i * 5;

			int x =  getInteger(newPosition, 5);
			x = x + 42;
			
			char c = (char) x;
			stringBuilder.append(c);

		}

		return stringBuilder.toString().trim();
	}

}