// fil InnBBUtBB.java
import inf101.*;

// BB st?r for 'Bits & Bytes'

/**
* Utvider klassen Inn med metode for ? lese enkeltbit eller
* en kode p? opptil 21000 verdier p? fil i en eller to byter,
* og en metode for ? lese neste ord p? fila.
************************************************************/
class InnBB extends Inn {

	private int bitInnVerdi = 0;
	private int antBitIgjen  = 0;

    /** Avoids cotrol characters. : 10, 13, 128-160
    * @param i a byte value read from file with inChar()
    * @return 'code' as used when calling corresponding utKonv(int code)
    */
	int inKonv (int i) {
			int ret = i;
			if (i >= 10 ) ret -= 4;
			if (i >= 128 ) ret -= 32;
			return ret;
	}

	InnBB (String s) { super(s);}
	InnBB (){super();}

    /**
	*  Reads next code from file. : lower 100 values (2 digits in code)  in byte 1.
    *  if value of code on file  >= 100  then byte 1 > 100 and byte 2 = upper 3 digits (up to 210 values).
	*  @return  max value = 210*100 (can easily be extended to 3,4.. byte encoding)
    *************************************************************************/
	public int innKode( ) {
		    int c,k;
			c = inKonv((int) inChar());

			if (c >= 100) {
				k = c - 100;
				c = inKonv((int) inChar());
				return c*100 +k;
			} else {
				return c;
			}
	} // end innKode


	/**
	* Reads next word from file. Skips whitespace as determined
	* by parameter to inString()
	*/
	public String lesNesteOrd () {
			return inString(" "); // Pr?v her andre avgrnsninger i tillegg som :.,\n-
	}

	/**
	*  Reads next 13 bit Huffman code from file.
	*/
    int innBKode() {
		// gets 2 byte input from utKode. All leading bits might be '0'
		int i = innKode();
		if ( i >= 20000 ) bitInnVerdi = i - 20000;
		else bitInnVerdi = i;

		return bitInnVerdi;

	} // end outKode


	/**
	* Writes bit value in int i' to file: 14 bits in two bytes.
	* Remember to call flushBit to get out last bits
	*/
	public int innBit() {
		if (antBitIgjen == 0 ) {
			bitInnVerdi = innBKode() << (31-13);  // upper bit to read
			antBitIgjen = 13;
		}
		antBitIgjen--;
		bitInnVerdi <<= 1;
		if ( bitInnVerdi < 0) return 1 ; else return 0;

	} // end innBit



} // end class InnB


/**
* Utvider klassen Ut med metode for ? skrive enten bitm?nstre eller
* en kode p? opptil 21000 verdier p? fil i en eller to byter.
* BB = Bit og Byte
************************************************************/
class UtBB extends Ut {

	private int bitUtVerdi = 0;
	private int antBitSkrevet = 0;

   /** Avoids cotrol characters. : 10, 13, 128-160
       @return 'code' to be output on file, read by corresponding innKonv(int code) **/
	int utKonv(int i) {
				int ret = i;
				if (i >= 10 ) ret += 4;
			    if (i >= 124 ) ret += 32;
			    return ret;
			}

	UtBB (String s) { super(s);}
	UtBB (){super();}

    /**
	*  Writes code 'k' to file: lower 100 values (2 digits in code)  in byte 1.
    *  if value of code >= 100  then byte 1 >=100 and byte 2 = upper 3 digits (up to 210 values).
	*  Max code value = 210*100 (can easily be extended to 3,4.. byte encoding)
    */
	public void utKode(int k) {
        int c1,c2;

		if (k >= 100) {
			c1 = utKonv( (k %100) + 100 );
			outChar( (char) c1);
			c2 = utKonv(k/100);
			outChar( (char) c2 );

		} else {
			c1 =  utKonv(k);
			outChar((char)c1);
        }
	} // end outKode

   /**
	*  Writes code 'k' to file: lower 100 values (2 digits in code)  in byte 1.
    *  if value of code >= 100  then byte 1 >=100 and byte 2 = upper 3 digits (up to 210 values).
	*  Max code value = 210*100 (can easily be extended to 3,4.. byte encoding)
    */
	public void utBKode(int k) {
		// assure 2 byte output from utKode. All leading bits might be '0'
		if ( k < 100) utKode( k + 20000);
        else utKode(k);

	} // end outKode



   /**
	* Writes bit value in int i' to file: 13 bits in two bytes.
	* Assumes i == 0 or i == 1.
	* Remember to call flushBit to get out last bits
    *************************************************************************/
	public void utBit(int i) {
		antBitSkrevet++;
		bitUtVerdi = (bitUtVerdi <<1) | i;
		if (antBitSkrevet == 13 ) {
			utBKode(bitUtVerdi);
			bitUtVerdi = 0;
			antBitSkrevet = 0;
		}

	} // end utBit


   /**
	* Writes 'len' bitsin int 'i' to file.
	* Remember to call flushBit to get out last bits
    *************************************************************************/
	public void utHuffKode(int i, int len) {

		if (13 - antBitSkrevet > len ) {
			antBitSkrevet += len;
			bitUtVerdi = (bitUtVerdi <<len) + i;
		} else if (13 - antBitSkrevet == len) {
			utBKode((bitUtVerdi <<len) + i);
			antBitSkrevet = 0;
			bitUtVerdi = 0;
		} else {
			// too many bits in i
			int len1 = (13 - antBitSkrevet),
			    len2 = len - len1;
			int kode1 = i >>> len2,
			    kode2 = i - ( kode1 << len2);
			utBKode((bitUtVerdi <<len1) + kode1);
			bitUtVerdi = 0;
			antBitSkrevet = 0;
			utHuffKode(kode2,len2);  // take any code length
		}
	} // end utHiffKode



   /**
	* Flushes bitbuffer used by utBit & utHuffKode
    */
	public void flushBit() { if (antBitSkrevet > 0 ) {
			utKode(bitUtVerdi<<(13 -antBitSkrevet));
			bitUtVerdi = 0;
			antBitSkrevet = 0;
        }
	} // end flushBit

} // end class UtB