Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pack/huffinit.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1993-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* huffman coding initialization
23
*
24
* David Korn
25
* AT&T Laboratories
26
*/
27
28
#include "huffman.h"
29
#include <error.h>
30
31
#define END (1<<CHAR_BIT)
32
33
/* the heap */
34
typedef struct
35
{
36
long int count;
37
int node;
38
} Heap_t;
39
40
static long count[END+1];
41
static int lastnode;
42
static void heapify(Heap_t*, int, int);
43
44
Huff_t *huffinit(Sfio_t *infile, Sfoff_t insize)
45
{
46
register int n;
47
register unsigned char *inbuff;
48
register int i, c;
49
register Huff_t *hp;
50
register Sfoff_t size = insize;
51
int parent[2*END+1];
52
Heap_t heap[END+2];
53
if(!(hp=newof(0, Huff_t, 1, 0)))
54
{
55
errno = ENOMEM;
56
return((Huff_t*)0);
57
}
58
for (i=0; i<END; i++)
59
count[i] = 0;
60
while(inbuff=(unsigned char*)sfreserve(infile,SF_UNBOUND,0))
61
{
62
n = sfvalue(infile);
63
if(size>=0)
64
{
65
if(n > size)
66
n = size;
67
size -= n;
68
}
69
hp->insize +=n;
70
while (n > 0)
71
count[inbuff[--n]]++;
72
}
73
if(n < 0)
74
{
75
huffend(hp);
76
return((Huff_t*)0);
77
}
78
for (i=0; i<END; i++)
79
count[i] += count[i];
80
count[END] = 1;
81
/* put occurring chars in heap with their counts */
82
for (i=END; i>=0; i--)
83
{
84
parent[i] = 0;
85
if (count[i] > 0)
86
{
87
heap[++n].count = count[i];
88
heap[n].node = i;
89
}
90
}
91
hp->nchars = n-1;
92
for (i=n/2; i>=1; i--)
93
heapify(heap,i,n);
94
/* build Huffman tree */
95
lastnode = END;
96
while (n > 1)
97
{
98
parent[heap[1].node] = ++lastnode;
99
size = heap[1].count;
100
heap[1] = heap[n];
101
n--;
102
heapify(heap,1,n);
103
parent[heap[1].node] = lastnode;
104
heap[1].node = lastnode;
105
heap[1].count += size;
106
heapify(heap,1,n);
107
}
108
parent[lastnode] = 0;
109
/* assign lengths to encoding for each character */
110
size = hp->maxlev = 0;
111
for (i=1; i<=HUFFLEV; i++)
112
hp->levcount[i] = 0;
113
for (i=0; i<=END; i++)
114
{
115
c = 0;
116
for(n=parent[i]; n!=0; n=parent[n])
117
c++;
118
hp->levcount[c]++;
119
hp->length[i] = c;
120
if (c > hp->maxlev)
121
hp->maxlev = c;
122
size += c*(count[i]>>1);
123
}
124
hp->outsize = (size+CHAR_BIT-1)/CHAR_BIT;
125
return(hp);
126
}
127
128
/* makes a heap out of heap[i],...,heap[n] */
129
static void heapify (register Heap_t *heap,register int i,register int n)
130
{
131
register int k;
132
register int lastparent = n/2;
133
Heap_t heapsubi;
134
heapsubi = heap[i];
135
while (i <= lastparent)
136
{
137
k = 2*i;
138
if (heap[k].count > heap[k+1].count && k < n)
139
k++;
140
if (heapsubi.count < heap[k].count)
141
break;
142
heap[i] = heap[k];
143
i = k;
144
}
145
heap[i] = heapsubi;
146
}
147
148