/* */

22 de mayo de 2008

TP - Compresor Huffman

.
Análisis de untSz.pas

Por último analizaremos la unit común a szzip.pas y szunzip.pas en la que se define la sección type y las funciones de manipulación a nivel bit.

untSz.pas

  1:
2:unit untSz;
3:
4:interface
5:
6: // ----------
7: // CONSTANTES
8: // ----------
9:
10: const
11: EXTENSION_COD='.szcod';
12: EXTENSION_DAT='.szzip';
13: EXTENSION_LEN='.szlen';
14:
15:
16: // -------------------
17: // DEFINICION DE TIPOS
18: // -------------------
19:
20: type
21:
22: PNodo = ^Nodo;
23: Nodo = record
24: c: byte;
25: n: comp;
26: izq: PNodo;
27: der: PNodo;
28: sig: PNodo;
29: end;
30:
31: // tipo para array de 16 bytes
32: T16b = array[0..15] of byte;
33:
34: // registro para el array
35: RArray = record
36: n: comp; // cantidad de ocurrencias
37: cod: T16b; // codigo asignado (max 128 bits)
38: nCod: byte; // longitud del codigo (max 128)
39: end;
40:
41: // tipo para el array
42: TArray = array[0..255] of RArray;
43:
44: // tipo para el archivo
45: FByte = file of byte;
46:
47: // registro para el archivo len
48: RLen = record
49: c:byte;
50: n:comp;
51: end;
52:
53: // tipo para el archivo len
54: FLen = file of RLen;
55:
56:
57: // -----------------------
58: // DEFINICION DE FUNCIONES
59: // -----------------------
60:
61: // retorna 2 a la n
62: // ejemplo: potencia2(3) = 8
63: function potencia2(n:byte):byte;
64:
65: // dado un byte retorna un string con su
66: // representacion binaria
67: // por ejemplo: si b es 36 => b es 00100100 =>
68: // byteToBin(b) retorna '00100100'
69: function byteToBin(b: byte): string[8];
70:
71: // retorna 1 o 0 segun el bit de la posicion i
72: // sea 1 o 0, contanto desde cero de izquierda a
73: // derecha
74: // ejemplo: si b es 25 => b es 00011001 =>
75: // getBitAt(b,2) retorna 0
76: // getBitAt(b,3) retorna 1
77: function getBitAt(b: byte; i: byte): byte;
78:
79: // setea en 1 o en 0 el bit de la posicion pos en
80: // el byte b, contando de cero a 7 de izquierda
81: // a derecha
82: // ejemplo: si b es 0 => b es 00000000 =>
83: // setBitAt(b,0,1) retorna 10000000 => 128
84: procedure setBitAt(var b:byte; pos:byte; val:byte);
85:
86: // copia en tgt los bites de src contenidos entre
87: // las posiciones desde y hasta (no inclusive)
88: // con un desplazamiento offset
89: procedure copiarBits(var tgt: byte;src:byte
90: ;desde,hasta,offset:shortint);
91:
92: // (sobrecarga)
93: // iden pero trabajando sobre un T16b. La salida
94: // contendra solo los primeros x bits comenzando
95: // a contar desde la izquierda
96: function byteToBin(b: T16b; x:byte): string;
97:
98: // (sobrecarga)
99: // idem pero trabaja sobre un T16b
100: function getBitAt(b:T16b; i:byte): byte;
101:
102: // (sobrecarga)
103: // iden pero trabajando sobre un T16b
104: procedure setBitAt(var b:T16b; pos:byte; val:byte);
105:
106: // asigna ceros a un T16b
107: procedure setCeros(var b:T16b);
108:
109: // permite inicializar un T16b en funcion de los
110: // unos y ceros contenidos en sBin
111: // ejemplo: si sBin es: '100110011001100'
112: // entonces asigna exactamente esos unos y ceros
113: // a tgt (comenzando desde la izquierda y
114: // completando con ceros los bits restantes
115: procedure setBits(var tgt:T16b; sBin:string);
116:
117:
118: // FUNCIONES PARA DEBUG (se proveen resueltas)
119:
120: // muestra por pantalla el "contenido" de un
121: // nodo ndo mostrando su campo c, n, y si
122: // sig<>NIL entonces tambien muestra ndo^.sig^.n
123: procedure mostrarNodo(ndo:PNodo);
124:
125: // recorre la lista e invoca a mostrarNodo por
126: // cada nodo recorrido
127: procedure mostrarLista(lst: PNodo);
128:
129: // recorre el arbol en inOrden mostrando el
130: // contenido de sus nodos
131: procedure mostrarArbol(p:PNodo);
132:
133:
134:implementation
135:
136:// :
137:// :
138:// :
139:
140:end.
141:

La función potencia2 (línea 63) recibe un valor n y debe retornar la potencia n-ésima de 2. Por ejemplo si n es 5 retorna 2 "elevado a la" 5 = 32.

En la línea 69 vemos la función byteToBin. Esta función se utiliza para debuggear. Recibe un byte y retorna un string de 8 caracteres "unos y ceros" tal que representen en binario al byte recibido. La función está sobrecargada (ver línea 96) de forma tal que pueda aplicarse tanto a un tipo byte como a un tipo T16b.

En las líneas 77 y 84 se define la funcion getBitAt y el procedimiento setBitAt. La primera recibe un byte y una posición (contando de izquierda a derecha comenzando desde cero) y retorna 1 o 0 según el byte que reciba como parámetro tenga 1 o 0 en dicha posición. La segunda recibe un byte, una posición y un valor 1 o 0 y asigna ese valor en el bit del byte cuya posición se indica en el parámetro (siempre contando desde cero y de izquierda a derecha).

Estas funciones también están sobrecargadas para trabajar con T16b (líneas 100 y 104).

En la línea 89 vemos el procedimiento copiarBits. Basicamente lo que debe hacer es copiar un conjunto de bits de un byte (src) a otro byte (tgt). El conjunto de bits a copiar se delimita por los parámetros desde y hasta. El parámetro offset marca el desplazamiento.

Veamos un ejemplo de como debe funcionar este procedimiento:
   1:
2:uses untSz;
3:
4:var src,tgt:byte;
5:begin
6: src:=231; // 11100111
7: tgt:=0; // 00000000
8:
9: // copio del bit 2 al 6 con offset 0
10: copiarBits(tgt,src,2,6,0);
11: writeln( byteToBin(tgt) ); // imprime: 00100100
12:
13: // copio del bit 2 al 6 con offset 2
14: tgt:=0; // vuelvo todo a cero
15: copiarBits(tgt,src,2,6,2);
16: writeln( byteToBin(tgt) ); // imprime: 00001001
17:
18: // copio del bit 2 al 6 con offset -2
19: tgt:=0; // vuelvo todo a cero
20: copiarBits(tgt,src,2,6,-2);
21: writeln( byteToBin(tgt) ); // imprime: 10010000
22:end.
23:

En la línea 107 se define el procedimiento setCeros que recibe un T16b para inicializarlo en cero. Recordemos que un T16b no es más que un array de 16 bytes (numerados de 0 a 15) por lo tanto para resolver este procedimiento simplemente hay que recorrer el T16b asignando cero en cada posición.


El siguiente programa utiliza y prueba el funcionamiento de todas las funciones definidas en untSz.pas. El alumno puede utilizarlo como caso de prueba para asegurarse que las funciones están correctamente desarrolladas.

testUntSz.pas
   1:
2:uses untSz;
3:
4:var a,b,pos:byte; h:T16b;
5:begin
6: // ------------------------------
7: // testeo de la funcion potencia2
8: // ------------------------------
9:
10: // debe mostrar 64
11: a:=6;
12: writeln( 'potencia2(',a,') = ',potencia2(a) );
13:
14: // debe mostrar 1
15: a:=0;
16: writeln( 'potencia2(',a,') = ',potencia2(a) );
17:
18: // debe mostrar 128
19: a:=7;
20: writeln( 'potencia2(',a,') = ',potencia2(a) );
21:
22:
23: // ------------------------------
24: // testeo de la funcion byteToBin
25: // ------------------------------
26:
27: // debe mostrar '11001001'
28: a:=201;
29: writeln( 'byteToBin(',a,') = ',byteToBin(a) );
30:
31: // debe mostrar '11111111'
32: a:=255;
33: writeln( 'byteToBin(',a,') = ',byteToBin(a) );
34:
35: // debe mostrar '00000000'
36: a:=0;
37: writeln( 'byteToBin(',a,') = ',byteToBin(a) );
38:
39: // -----------------------------
40: // testeo de la funcion getBitAt
41: // -----------------------------
42:
43: a:=201;
44:
45: // debe retornar 0
46: pos:=3;
47: writeln('a=',byteToBin(a),', ',getBitAt(a,pos));
48:
49: // debe retornar 1
50: pos:=4;
51: writeln('a=',byteToBin(a),', ',getBitAt(a,pos));
52:
53: // debe retornar 1
54: pos:=0;
55: writeln('a=',byteToBin(a),', ',getBitAt(a,pos));
56:
57: // debe retornar 1
58: pos:=7;
59: writeln('a=',byteToBin(a),', ',getBitAt(a,pos));
60:
61: // -----------------------------
62: // testeo de la funcion setBitAt
63: // -----------------------------
64:
65: a:=0;
66:
67: // debe mostrar '10000000'
68: pos:=0;
69: setBitAt(a,pos,1);
70: writeln('a=',byteToBin(a));
71:
72: // debe mostrar '10001000'
73: pos:=4;
74: setBitAt(a,pos,1);
75: writeln('a=',byteToBin(a));
76:
77: // debe mostrar '00001000'
78: pos:=0;
79: setBitAt(a,pos,0);
80: writeln('a=',byteToBin(a));
81:
82: // -------------------------------------
83: // testeo de la funcion byteToBin (T16b)
84: // -------------------------------------
85:
86: // debe mostrar 12 ceros '000000000000'
87: setCeros(h);
88: writeln('h=',byteToBin(h,12));
89:
90: // -----------------------------------
91: // testeo de la funcion setBits (T16b)
92: // -----------------------------------
93:
94: // tiene que mostrar '11100111001110011010000'
95: setBits(h,'1110011100111001101');
96: writeln('h=',byteToBin(h,23));
97:
98: // ------------------------------------
99: // testeo de la funcion setBitAt (T16b)
100: // ------------------------------------
101: setCeros(h);
102:
103: // tiene que mostrar '1000000000'
104: setBitAt(h,0,1);
105: writeln('h=',byteToBin(h,10));
106:
107: // tiene que mostrar '1000100000'
108: setBitAt(h,4,1);
109: writeln('h=',byteToBin(h,10));
110:
111: // ------------------------------------
112: // testeo de la funcion getBitAt (T16b)
113: // ------------------------------------
114:
115: setBits(h,'110011001100');
116:
117: // debe mostar 1
118: pos:=0;
119: b:=getBitAt(h,pos);
120: writeln('h=',byteToBin(h,15),', ',b);
121:
122: // debe mostar 0
123: pos:=2;
124: b:=getBitAt(h,pos);
125: writeln('h=',byteToBin(h,15),', ',b);
126:
127: // debe mostar 1
128: pos:=4;
129: b:=getBitAt(h,pos);
130: writeln('h=',byteToBin(h,15),', ',b);
131:end.
132:

Luego de desarrollar todas las funciones y compilar este programa la salida debe ser la siguiente: