huffman/src/display.c

148 lines
4.3 KiB
C

#include "common.h"
#include "display.h"
#include "huftree.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
/**
* Détermine la profondeur maximale de l'arbre de Huffman donné
*/
static int _treeDepth(HufTree);
/**
* Sous-fonction pour l'affichage récursif d'un arbre de Huffman
*/
static void _subPrintTree(HufTree, wchar_t*, int);
/**
* Transforme le caractère donné en espace s'il est non-imprimable
* ou le laisse tel quel sinon
*/
static char _safeChar(char input);
// Drapeau pour l'affichage verbeux ou non-verbeux
static int is_verbose = FALSE;
void printVerbose(const char* format, ...) {
if (is_verbose) {
va_list args_list;
va_start(args_list, format);
vfprintf(stderr, format, args_list);
va_end(args_list);
}
}
void setVerbose(int flag) {
is_verbose = flag;
}
int isVerbose() {
return is_verbose;
}
void printTree(HufTree tree) {
if (tree == NULL) {
// Cas particulier : arbre vide
printVerbose("(Arbre vide.)\n");
} else {
// Allocation d'un tampon suffisamment grand pour contenir
// les indentations des sommets les plus profonds de l'arbre
wchar_t* buffer = malloc(_treeDepth(tree) * 4 * sizeof(*buffer));
_subPrintTree(tree, buffer, 0);
free(buffer);
}
}
void _subPrintTree(HufTree tree, wchar_t* buffer, int length) {
if (tree->child_l != NULL && tree->child_r != NULL) {
// Affichage d'un sommet avec enfants, on montre
// la probabilité somme des enfants
printVerbose("\n");
// Affichage du fils gauche. Augmentation du préfixe
// pour l'affichage des enfants du fils gauche
buffer[length] = '\0';
printVerbose("%ls├── ", buffer);
buffer[length] = L'';
buffer[length + 1] = ' ';
buffer[length + 2] = ' ';
buffer[length + 3] = ' ';
buffer[length + 4] = '\0';
_subPrintTree(tree->child_l, buffer, length + 4);
// Affichage du fils droite. Augmentation du préfixe
// pour l'affichage des enfants du fils droit
buffer[length] = '\0';
printVerbose("%ls└── ", buffer);
buffer[length] = ' ';
_subPrintTree(tree->child_r, buffer, length + 4);
} else {
// Affichage d'une feuille de l'arbre, correspondant
// à un caractère du corpus
printVerbose("%c\n", _safeChar(tree->value));
}
}
int _treeDepth(HufTree tree) {
if (tree->child_l != NULL && tree->child_r != NULL) {
int left = _treeDepth(tree->child_l);
int right = _treeDepth(tree->child_r);
return (left > right ? left : right) + 1;
} else {
return 1;
}
}
void printCountsTable(bytecount* table, bytecount total, size_t size) {
printVerbose("┌─┬────┬────────┐\n");
printVerbose("│C│code│effectif│\n");
printVerbose("├─┼────┼────────┤\n");
for (size_t i = 0; i < size; i++) {
if (table[i] != 0) {
printVerbose("│%c│%4d│%8llu│\n", _safeChar(i), (int) i, table[i]);
}
}
printVerbose("├─┴────┼────────┤\n");
printVerbose("│ Total│%8llu│\n", total);
printVerbose("└──────┴────────┘\n");
}
void printLabelsTable(char** table, size_t size) {
printVerbose("┌─┬────┬────────────────┐\n");
printVerbose("│C│code│ étiquette│\n");
printVerbose("├─┼────┼────────────────┤\n");
double total_length = 0;
size_t label_count = 0;
for (size_t i = 0; i < size; i++) {
if (table[i] != 0) {
printVerbose("│%c│%4d│%16s│\n", _safeChar(i), (int) i, table[i]);
total_length += strlen(table[i]);
label_count++;
}
}
printVerbose("├─┴────┴───┬────────────┤\n");
printVerbose("│Long. moy.│%12.4lf│\n", total_length / label_count);
printVerbose("└──────────┴────────────┘\n");
}
char _safeChar(char input) {
if (input < 32 || input == 127) {
return ' ';
}
return input;
}