Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include "types.h"
33
#include "enc_types.h"
34
#include "file.h"
35
#include "utility.h"
36
 
37
 
38
/*
39
    BITMASKS
40
 
41
    The nth value in this array can be used to extract the bottom n
42
    bits of a value.
43
*/
44
 
45
static unsigned long mask [] = {
46
    0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
47
} ;
48
 
49
 
50
/*
51
    SIZE OF A STANDARD BITSTREAM
52
 
53
    Each bitstream contains BITSTREAM_SIZE bytes.  It is worth garbage
54
    collecting if it has CRITICAL_SIZE bytes free when it is closed.
55
*/
56
 
57
#define BITSTREAM_SIZE		100
58
#define CRITICAL_SIZE		50
59
 
60
 
61
/*
62
    LIST OF FREE BITSTREAMS
63
 
64
    Bitstreams are allocated from this list.
65
*/
66
 
67
static bitstream *free_bitstreams = null ;
68
 
69
 
70
/*
71
    CREATE A NEW BITSTREAM
72
 
73
    A new bitstream is allocated and initialized.
74
*/
75
 
76
bitstream *new_bitstream
77
    PROTO_Z ()
78
{
79
    unsigned i ;
80
    bitstream *p ;
81
    if ( free_bitstreams == null ) {
82
	p = alloc_nof ( bitstream, 1 ) ;
83
	p->length = BITSTREAM_SIZE ;
84
	p->source = alloc_nof ( byte, BITSTREAM_SIZE + 10 ) ;
85
    } else {
86
	p = free_bitstreams ;
87
	free_bitstreams = p->next ;
88
    }
89
    for ( i = 0 ; i < p->length ; i++ ) p->source [i] = 0 ;
90
    p->bytes = 0 ;
91
    p->bits = 0 ;
92
    p->next = null ;
93
    p->end = p ;
94
    return ( p ) ;
95
}
96
 
97
 
98
#if 0
99
 
100
/*
101
    CLOSE OFF A BITSTREAM
102
 
103
    The bitstream p is closed off and any free space is garbage collected.
104
    (Not currently used.)
105
*/
106
 
107
static void close_bitstream
108
    PROTO_N ( ( p ) )
109
    PROTO_T ( bitstream *p )
110
{
111
    bitstream *q ;
112
    int used = p->end->bytes + 4 ;
113
    int left = p->end->length - used ;
114
    if ( left < CRITICAL_SIZE ) return ;
115
    q = alloc_nof ( bitstream, 1 ) ;
116
    q->length = left ;
117
    q->source = p->end->source + used ;
118
    q->next = free_bitstreams ;
119
    free_bitstreams = q ;
120
    p->end->length = used ;
121
    return ;
122
}
123
 
124
#endif
125
 
126
 
127
/*
128
    PRINT A BITSTREAM
129
 
130
    The bitstream p is dumped to the output file.
131
*/
132
 
133
void print_bitstream
134
    PROTO_N ( ( p ) )
135
    PROTO_T ( bitstream *p )
136
{
137
    unsigned r = 0 ;
138
    unsigned long buff = 0 ;
139
    for ( ; p ; p = p->next ) {
140
	unsigned i ;
141
	for ( i = 0 ; i < p->bytes ; i++ ) {
142
	    byte b = p->source [i] ;
143
	    if ( r == 0 ) {
144
		IGNORE fputc ( ( int ) b, output ) ;
145
	    } else {
146
		buff = ( buff << BYTESIZE ) | ( ( unsigned long ) b ) ;
147
		IGNORE fputc ( ( int ) ( ( buff >> r ) & 0xff ), output ) ;
148
		buff &= mask [r] ;
149
	    }
150
	}
151
	if ( p->bits ) {
152
	    byte b = p->source [ p->bytes ] ;
153
	    b = ( byte ) ( ( unsigned ) b >> ( BYTESIZE - p->bits ) ) ;
154
	    buff = ( buff << p->bits ) | ( ( unsigned long ) b ) ;
155
	    r += p->bits ;
156
	    if ( r >= BYTESIZE ) {
157
		r -= BYTESIZE ;
158
		IGNORE fputc ( ( int ) ( ( buff >> r ) & 0xff ), output ) ;
159
		buff &= mask [r] ;
160
	    }
161
	}
162
    }
163
    if ( r ) {
164
	buff <<= ( BYTESIZE - r ) ;
165
	IGNORE fputc ( ( int ) buff, output ) ;
166
    }
167
    return ;
168
}
169
 
170
 
171
/*
172
    FIND THE LENGTH OF A BITSTREAM
173
 
174
    The length of the bitstream p (in bits) is returned.
175
*/
176
 
177
long bitstream_length
178
    PROTO_N ( ( p ) )
179
    PROTO_T ( bitstream *p )
180
{
181
    unsigned n = 0 ;
182
    for ( ; p ; p = p->next ) n += ( BYTESIZE * p->bytes ) + p->bits ;
183
    return ( ( long ) n ) ;
184
}
185
 
186
 
187
/*
188
    JOIN TWO BITSTREAMS
189
 
190
    The bitstream q is appended to p.
191
*/
192
 
193
void join_bitstreams
194
    PROTO_N ( ( p, q ) )
195
    PROTO_T ( bitstream *p X bitstream *q )
196
{
197
#if 0
198
    close_bitstream ( p ) ;
199
#endif
200
    p->end->next = q ;
201
    p->end = q->end ;
202
    return ;
203
}
204
 
205
 
206
/*
207
    ADD A NUMBER OF BITS TO THE END OF A BITSTREAM
208
 
209
    n bits of value v are added to the end of the bitstream p.
210
*/
211
 
212
void enc_bits
213
    PROTO_N ( ( p, n, v ) )
214
    PROTO_T ( bitstream *p X int n X long v )
215
{
216
    byte *t ;
217
    bitstream *q = p->end ;
218
    unsigned m = ( unsigned ) n ;
219
    unsigned left = BYTESIZE - q->bits ;
220
    unsigned long w = ( unsigned long ) v ;
221
    if ( left == 0 ) {
222
	left = BYTESIZE ;
223
	q->bits = 0 ;
224
	q->bytes++ ;
225
	if ( q->bytes >= q->length ) {
226
	    q->next = new_bitstream () ;
227
	    q = q->next ;
228
	    p->end = q ;
229
	}
230
	q->source [ q->bytes ] = 0 ;
231
    }
232
    if ( m > left ) {
233
	enc_bits ( p, ( int ) ( m - left ), ( long ) ( w >> left ) ) ;
234
	enc_bits ( p, ( int ) left, ( long ) ( w & mask [ left ] ) ) ;
235
	return ;
236
    }
237
    w <<= ( left - m ) ;
238
    t = q->source + q->bytes ;
239
    *t = ( byte ) ( *t | ( byte ) w ) ;
240
    q->bits += m ;
241
    return ;
242
}
243
 
244
 
245
/*
246
    ALIGN A BITSTREAM TO A BYTE BOUNDARY
247
 
248
    The bitstream p is aligned to a byte boundary.
249
*/
250
 
251
void align_bitstream
252
    PROTO_N ( ( p ) )
253
    PROTO_T ( bitstream *p )
254
{
255
    int bit = ( int ) ( bitstream_length ( p ) % BYTESIZE ) ;
256
    if ( bit ) enc_bits ( p, BYTESIZE - bit, ( long ) 0 ) ;
257
    return ;
258
}