comparison spandsp-0.0.6pre17/src/v42bis.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v42bis.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2005 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: v42bis.c,v 1.37 2009/02/10 13:06:47 steveu Exp $
26 */
27
28 /* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED.
29 Currently it performs the core compression and decompression functions OK.
30 However, a number of the bells and whistles in V.42bis are incomplete. */
31
32 /*! \file */
33
34 #if defined(HAVE_CONFIG_H)
35 #include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <inttypes.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <ctype.h>
45 #include <assert.h>
46
47 #include "spandsp/telephony.h"
48 #include "spandsp/logging.h"
49 #include "spandsp/bit_operations.h"
50 #include "spandsp/v42bis.h"
51
52 #include "spandsp/private/logging.h"
53 #include "spandsp/private/v42bis.h"
54
55 /* Fixed parameters from the spec. */
56 #define V42BIS_N3 8 /* Character size (bits) */
57 #define V42BIS_N4 256 /* Number of characters in the alphabet */
58 #define V42BIS_N5 (V42BIS_N4 + V42BIS_N6) /* Index number of first dictionary entry used to store a string */
59 #define V42BIS_N6 3 /* Number of control codewords */
60
61 /* Control code words in compressed mode */
62 enum
63 {
64 V42BIS_ETM = 0, /* Enter transparent mode */
65 V42BIS_FLUSH = 1, /* Flush data */
66 V42BIS_STEPUP = 2 /* Step up codeword size */
67 };
68
69 /* Command codes in transparent mode */
70 enum
71 {
72 V42BIS_ECM = 0, /* Enter compression mode */
73 V42BIS_EID = 1, /* Escape character in data */
74 V42BIS_RESET = 2 /* Force reinitialisation */
75 };
76
77 static __inline__ void push_compressed_raw_octet(v42bis_compress_state_t *ss, int octet)
78 {
79 ss->output_buf[ss->output_octet_count++] = (uint8_t) octet;
80 if (ss->output_octet_count >= ss->max_len)
81 {
82 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
83 ss->output_octet_count = 0;
84 }
85 }
86 /*- End of function --------------------------------------------------------*/
87
88 static __inline__ void push_compressed_code(v42bis_compress_state_t *ss, int code)
89 {
90 ss->output_bit_buffer |= code << (32 - ss->v42bis_parm_c2 - ss->output_bit_count);
91 ss->output_bit_count += ss->v42bis_parm_c2;
92 while (ss->output_bit_count >= 8)
93 {
94 push_compressed_raw_octet(ss, ss->output_bit_buffer >> 24);
95 ss->output_bit_buffer <<= 8;
96 ss->output_bit_count -= 8;
97 }
98 }
99 /*- End of function --------------------------------------------------------*/
100
101 static __inline__ void push_compressed_octet(v42bis_compress_state_t *ss, int code)
102 {
103 ss->output_bit_buffer |= code << (32 - 8 - ss->output_bit_count);
104 ss->output_bit_count += 8;
105 while (ss->output_bit_count >= 8)
106 {
107 push_compressed_raw_octet(ss, ss->output_bit_buffer >> 24);
108 ss->output_bit_buffer <<= 8;
109 ss->output_bit_count -= 8;
110 }
111 }
112 /*- End of function --------------------------------------------------------*/
113
114 SPAN_DECLARE(int) v42bis_compress(v42bis_state_t *s, const uint8_t *buf, int len)
115 {
116 int ptr;
117 int i;
118 uint32_t octet;
119 uint32_t code;
120 v42bis_compress_state_t *ss;
121
122 ss = &s->compress;
123 if ((s->v42bis_parm_p0 & 2) == 0)
124 {
125 /* Compression is off - just push the incoming data out */
126 for (i = 0; i < len - ss->max_len; i += ss->max_len)
127 ss->handler(ss->user_data, buf + i, ss->max_len);
128 if (i < len)
129 ss->handler(ss->user_data, buf + i, len - i);
130 return 0;
131 }
132 ptr = 0;
133 if (ss->first && len > 0)
134 {
135 octet = buf[ptr++];
136 ss->string_code = octet + V42BIS_N6;
137 if (ss->transparent)
138 push_compressed_octet(ss, octet);
139 ss->first = FALSE;
140 }
141 while (ptr < len)
142 {
143 octet = buf[ptr++];
144 if ((ss->dict[ss->string_code].children[octet >> 5] & (1 << (octet & 0x1F))))
145 {
146 /* The leaf exists. Now find it in the table. */
147 /* TODO: This is a brute force scan for a match. We need something better. */
148 for (code = 0; code < ss->v42bis_parm_c3; code++)
149 {
150 if (ss->dict[code].parent_code == ss->string_code && ss->dict[code].node_octet == octet)
151 break;
152 }
153 }
154 else
155 {
156 /* The leaf does not exist. */
157 code = s->v42bis_parm_n2;
158 }
159 /* 6.3(b) If the string matches a dictionary entry, and the entry is not that entry
160 created by the last invocation of the string matching procedure, then the
161 next character shall be read and appended to the string and this step
162 repeated. */
163 if (code < ss->v42bis_parm_c3 && code != ss->latest_code)
164 {
165 /* The string was found */
166 ss->string_code = code;
167 ss->string_length++;
168 }
169 else
170 {
171 /* The string is not in the table. */
172 if (!ss->transparent)
173 {
174 /* 7.4 Encoding - we now have the longest matchable string, and will need to output the code for it. */
175 while (ss->v42bis_parm_c1 >= ss->v42bis_parm_c3 && ss->v42bis_parm_c3 <= s->v42bis_parm_n2)
176 {
177 /* We need to increase the codeword size */
178 /* 7.4(a) */
179 push_compressed_code(ss, V42BIS_STEPUP);
180 /* 7.4(b) */
181 ss->v42bis_parm_c2++;
182 /* 7.4(c) */
183 ss->v42bis_parm_c3 <<= 1;
184 /* 7.4(d) this might need to be repeated, so we loop */
185 }
186 /* 7.5 Transfer - output the last state of the string */
187 push_compressed_code(ss, ss->string_code);
188 }
189 /* 7.6 Dictionary updating */
190 /* 6.4 Add the string to the dictionary */
191 /* 6.4(b) The string is not in the table. */
192 if (code != ss->latest_code && ss->string_length < s->v42bis_parm_n7)
193 {
194 ss->latest_code = ss->v42bis_parm_c1;
195 /* 6.4(a) The length of the string is in range for adding to the dictionary */
196 /* If the last code was a leaf, it no longer is */
197 ss->dict[ss->string_code].leaves++;
198 ss->dict[ss->string_code].children[octet >> 5] |= (1 << (octet & 0x1F));
199 /* The new one is definitely a leaf */
200 ss->dict[ss->v42bis_parm_c1].parent_code = (uint16_t) ss->string_code;
201 ss->dict[ss->v42bis_parm_c1].leaves = 0;
202 ss->dict[ss->v42bis_parm_c1].node_octet = (uint8_t) octet;
203 /* 7.7 Node recovery */
204 /* 6.5 Recovering a dictionary entry to use next */
205 for (;;)
206 {
207 /* 6.5(a) and (b) */
208 if ((int) (++ss->v42bis_parm_c1) >= s->v42bis_parm_n2)
209 ss->v42bis_parm_c1 = V42BIS_N5;
210 /* 6.5(c) We need to reuse a leaf node */
211 if (ss->dict[ss->v42bis_parm_c1].leaves)
212 continue;
213 if (ss->dict[ss->v42bis_parm_c1].parent_code == 0xFFFF)
214 break;
215 /* 6.5(d) Detach the leaf node from its parent, and re-use it */
216 /* Possibly make the parent a leaf node again */
217 ss->dict[ss->dict[ss->v42bis_parm_c1].parent_code].leaves--;
218 ss->dict[ss->dict[ss->v42bis_parm_c1].parent_code].children[ss->dict[ss->v42bis_parm_c1].node_octet >> 5] &= ~(1 << (ss->dict[ss->v42bis_parm_c1].node_octet & 0x1F));
219 ss->dict[ss->v42bis_parm_c1].parent_code = 0xFFFF;
220 break;
221 }
222 }
223 else
224 {
225 ss->latest_code = 0xFFFFFFFF;
226 }
227 /* 7.8 Data compressibility test */
228 /* Filter on the balance of what went into the compressor, and what came out */
229 ss->compressibility_filter += ((((8*ss->string_length - ss->v42bis_parm_c2) << 20) - ss->compressibility_filter) >> 10);
230 if (ss->compression_mode == V42BIS_COMPRESSION_MODE_DYNAMIC)
231 {
232 /* Work out if it is appropriate to change between transparent and
233 compressed mode. */
234 if (ss->transparent)
235 {
236 if (ss->compressibility_filter > 0)
237 {
238 if (++ss->compressibility_persistence > 1000)
239 {
240 /* Schedule a switch to compressed mode */
241 ss->change_transparency = -1;
242 ss->compressibility_persistence = 0;
243 }
244 }
245 else
246 {
247 ss->compressibility_persistence = 0;
248 }
249 }
250 else
251 {
252 if (ss->compressibility_filter < 0)
253 {
254 if (++ss->compressibility_persistence > 1000)
255 {
256 /* Schedule a switch to transparent mode */
257 ss->change_transparency = 1;
258 ss->compressibility_persistence = 0;
259 }
260 }
261 else
262 {
263 ss->compressibility_persistence = 0;
264 }
265 }
266 }
267 if (ss->change_transparency)
268 {
269 if (ss->change_transparency < 0)
270 {
271 if (ss->transparent)
272 {
273 printf("Going compressed\n");
274 /* 7.8.1 Transition to compressed mode */
275 /* Switch out of transparent now, between codes. We need to send the octet which did not
276 match, just before switching. */
277 if (octet == ss->escape_code)
278 {
279 push_compressed_octet(ss, ss->escape_code++);
280 push_compressed_octet(ss, V42BIS_EID);
281 }
282 else
283 {
284 push_compressed_octet(ss, octet);
285 }
286 push_compressed_octet(ss, ss->escape_code++);
287 push_compressed_octet(ss, V42BIS_ECM);
288 ss->transparent = FALSE;
289 }
290 }
291 else
292 {
293 if (!ss->transparent)
294 {
295 printf("Going transparent\n");
296 /* 7.8.2 Transition to transparent mode */
297 /* Switch into transparent now, between codes, and the unmatched octet should
298 go out in transparent mode, just below */
299 push_compressed_code(ss, V42BIS_ETM);
300 ss->transparent = TRUE;
301 }
302 }
303 ss->change_transparency = 0;
304 }
305 /* 7.8.3 Reset function - TODO */
306 ss->string_code = octet + V42BIS_N6;
307 ss->string_length = 1;
308 }
309 if (ss->transparent)
310 {
311 if (octet == ss->escape_code)
312 {
313 push_compressed_octet(ss, ss->escape_code++);
314 push_compressed_octet(ss, V42BIS_EID);
315 }
316 else
317 {
318 push_compressed_octet(ss, octet);
319 }
320 }
321 }
322 return 0;
323 }
324 /*- End of function --------------------------------------------------------*/
325
326 SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *s)
327 {
328 v42bis_compress_state_t *ss;
329
330 ss = &s->compress;
331 if (!ss->transparent)
332 {
333 /* Output the last state of the string */
334 push_compressed_code(ss, ss->string_code);
335 /* TODO: We use a positive FLUSH at all times. It is really needed, if the
336 previous step resulted in no leftover bits. */
337 push_compressed_code(ss, V42BIS_FLUSH);
338 }
339 while (ss->output_bit_count > 0)
340 {
341 push_compressed_raw_octet(ss, ss->output_bit_buffer >> 24);
342 ss->output_bit_buffer <<= 8;
343 ss->output_bit_count -= 8;
344 }
345 /* Now push out anything remaining. */
346 if (ss->output_octet_count > 0)
347 {
348 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
349 ss->output_octet_count = 0;
350 }
351 return 0;
352 }
353 /*- End of function --------------------------------------------------------*/
354
355 #if 0
356 SPAN_DECLARE(int) v42bis_compress_dump(v42bis_state_t *s)
357 {
358 int i;
359
360 for (i = 0; i < V42BIS_MAX_CODEWORDS; i++)
361 {
362 if (s->compress.dict[i].parent_code != 0xFFFF)
363 {
364 printf("Entry %4x, prior %4x, leaves %d, octet %2x\n", i, s->compress.dict[i].parent_code, s->compress.dict[i].leaves, s->compress.dict[i].node_octet);
365 }
366 }
367 return 0;
368 }
369 /*- End of function --------------------------------------------------------*/
370 #endif
371
372 SPAN_DECLARE(int) v42bis_decompress(v42bis_state_t *s, const uint8_t *buf, int len)
373 {
374 int ptr;
375 int i;
376 int this_length;
377 uint8_t *string;
378 uint32_t code;
379 uint32_t new_code;
380 int code_len;
381 v42bis_decompress_state_t *ss;
382 uint8_t decode_buf[V42BIS_MAX_STRING_SIZE];
383
384 ss = &s->decompress;
385 if ((s->v42bis_parm_p0 & 1) == 0)
386 {
387 /* Compression is off - just push the incoming data out */
388 for (i = 0; i < len - ss->max_len; i += ss->max_len)
389 ss->handler(ss->user_data, buf + i, ss->max_len);
390 if (i < len)
391 ss->handler(ss->user_data, buf + i, len - i);
392 return 0;
393 }
394 ptr = 0;
395 code_len = (ss->transparent) ? 8 : ss->v42bis_parm_c2;
396 for (;;)
397 {
398 /* Fill up the bit buffer. */
399 while (ss->input_bit_count < 32 - 8 && ptr < len)
400 {
401 ss->input_bit_count += 8;
402 ss->input_bit_buffer |= (uint32_t) buf[ptr++] << (32 - ss->input_bit_count);
403 }
404 if (ss->input_bit_count < code_len)
405 break;
406 new_code = ss->input_bit_buffer >> (32 - code_len);
407 ss->input_bit_count -= code_len;
408 ss->input_bit_buffer <<= code_len;
409 if (ss->transparent)
410 {
411 code = new_code;
412 if (ss->escaped)
413 {
414 ss->escaped = FALSE;
415 if (code == V42BIS_ECM)
416 {
417 printf("Hit V42BIS_ECM\n");
418 ss->transparent = FALSE;
419 code_len = ss->v42bis_parm_c2;
420 }
421 else if (code == V42BIS_EID)
422 {
423 printf("Hit V42BIS_EID\n");
424 ss->output_buf[ss->output_octet_count++] = ss->escape_code - 1;
425 if (ss->output_octet_count >= ss->max_len - s->v42bis_parm_n7)
426 {
427 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
428 ss->output_octet_count = 0;
429 }
430 }
431 else if (code == V42BIS_RESET)
432 {
433 printf("Hit V42BIS_RESET\n");
434 }
435 else
436 {
437 printf("Hit V42BIS_???? - %" PRIu32 "\n", code);
438 }
439 }
440 else if (code == ss->escape_code)
441 {
442 ss->escape_code++;
443 ss->escaped = TRUE;
444 }
445 else
446 {
447 ss->output_buf[ss->output_octet_count++] = (uint8_t) code;
448 if (ss->output_octet_count >= ss->max_len - s->v42bis_parm_n7)
449 {
450 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
451 ss->output_octet_count = 0;
452 }
453 }
454 }
455 else
456 {
457 if (new_code < V42BIS_N6)
458 {
459 /* We have a control code. */
460 switch (new_code)
461 {
462 case V42BIS_ETM:
463 printf("Hit V42BIS_ETM\n");
464 ss->transparent = TRUE;
465 code_len = 8;
466 break;
467 case V42BIS_FLUSH:
468 printf("Hit V42BIS_FLUSH\n");
469 v42bis_decompress_flush(s);
470 break;
471 case V42BIS_STEPUP:
472 /* We need to increase the codeword size */
473 printf("Hit V42BIS_STEPUP\n");
474 if (ss->v42bis_parm_c3 >= s->v42bis_parm_n2)
475 {
476 /* Invalid condition */
477 return -1;
478 }
479 code_len = ++ss->v42bis_parm_c2;
480 ss->v42bis_parm_c3 <<= 1;
481 break;
482 }
483 continue;
484 }
485 if (ss->first)
486 {
487 ss->first = FALSE;
488 ss->octet = new_code - V42BIS_N6;
489 ss->output_buf[0] = (uint8_t) ss->octet;
490 ss->output_octet_count = 1;
491 if (ss->output_octet_count >= ss->max_len - s->v42bis_parm_n7)
492 {
493 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
494 ss->output_octet_count = 0;
495 }
496 ss->old_code = new_code;
497 continue;
498 }
499 /* Start at the end of the buffer, and decode backwards */
500 string = &decode_buf[V42BIS_MAX_STRING_SIZE - 1];
501 /* Check the received code is valid. It can't be too big, as we pulled only the expected number
502 of bits from the input stream. It could, however, be unknown. */
503 if (ss->dict[new_code].parent_code == 0xFFFF)
504 return -1;
505 /* Otherwise we do a straight decode of the new code. */
506 code = new_code;
507 /* Trace back through the octets which form the string, and output them. */
508 while (code >= V42BIS_N5)
509 {
510 if (code > 4095) {printf("Code is 0x%" PRIu32 "\n", code); exit(2);}
511 *string-- = ss->dict[code].node_octet;
512 code = ss->dict[code].parent_code;
513 }
514 *string = (uint8_t) (code - V42BIS_N6);
515 ss->octet = code - V42BIS_N6;
516 /* Output the decoded string. */
517 this_length = V42BIS_MAX_STRING_SIZE - (int) (string - decode_buf);
518 memcpy(ss->output_buf + ss->output_octet_count, string, this_length);
519 ss->output_octet_count += this_length;
520 if (ss->output_octet_count >= ss->max_len - s->v42bis_parm_n7)
521 {
522 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
523 ss->output_octet_count = 0;
524 }
525 /* 6.4 Add the string to the dictionary */
526 if (ss->last_length < s->v42bis_parm_n7)
527 {
528 /* 6.4(a) The string does not exceed N7 in length */
529 if (ss->last_old_code != ss->old_code
530 ||
531 ss->last_extra_octet != *string)
532 {
533 /* 6.4(b) The string is not in the table. */
534 ss->dict[ss->old_code].leaves++;
535 /* The new one is definitely a leaf */
536 ss->dict[ss->v42bis_parm_c1].parent_code = (uint16_t) ss->old_code;
537 ss->dict[ss->v42bis_parm_c1].leaves = 0;
538 ss->dict[ss->v42bis_parm_c1].node_octet = (uint8_t) ss->octet;
539 /* 6.5 Recovering a dictionary entry to use next */
540 for (;;)
541 {
542 /* 6.5(a) and (b) */
543 if (++ss->v42bis_parm_c1 >= s->v42bis_parm_n2)
544 ss->v42bis_parm_c1 = V42BIS_N5;
545 /* 6.5(c) We need to reuse a leaf node */
546 if (ss->dict[ss->v42bis_parm_c1].leaves)
547 continue;
548 /* 6.5(d) This is a leaf node, so re-use it */
549 /* Possibly make the parent a leaf node again */
550 if (ss->dict[ss->v42bis_parm_c1].parent_code != 0xFFFF)
551 ss->dict[ss->dict[ss->v42bis_parm_c1].parent_code].leaves--;
552 ss->dict[ss->v42bis_parm_c1].parent_code = 0xFFFF;
553 break;
554 }
555 }
556 }
557 /* Record the addition to the dictionary, so we can check for repeat attempts
558 at the next code - see II.4.3 */
559 ss->last_old_code = ss->old_code;
560 ss->last_extra_octet = *string;
561
562 ss->old_code = new_code;
563 ss->last_length = this_length;
564 }
565 }
566 return 0;
567 }
568 /*- End of function --------------------------------------------------------*/
569
570 SPAN_DECLARE(int) v42bis_decompress_flush(v42bis_state_t *s)
571 {
572 v42bis_decompress_state_t *ss;
573
574 ss = &s->decompress;
575 /* Push out anything remaining. */
576 if (ss->output_octet_count > 0)
577 {
578 ss->handler(ss->user_data, ss->output_buf, ss->output_octet_count);
579 ss->output_octet_count = 0;
580 }
581 return 0;
582 }
583 /*- End of function --------------------------------------------------------*/
584
585 #if 0
586 SPAN_DECLARE(int) v42bis_decompress_dump(v42bis_state_t *s)
587 {
588 int i;
589
590 for (i = 0; i < V42BIS_MAX_CODEWORDS; i++)
591 {
592 if (s->decompress.dict[i].parent_code != 0xFFFF)
593 {
594 printf("Entry %4x, prior %4x, leaves %d, octet %2x\n", i, s->decompress.dict[i].parent_code, s->decompress.dict[i].leaves, s->decompress.dict[i].node_octet);
595 }
596 }
597 return 0;
598 }
599 /*- End of function --------------------------------------------------------*/
600 #endif
601
602 SPAN_DECLARE(void) v42bis_compression_control(v42bis_state_t *s, int mode)
603 {
604 s->compress.compression_mode = mode;
605 switch (mode)
606 {
607 case V42BIS_COMPRESSION_MODE_ALWAYS:
608 s->compress.change_transparency = -1;
609 break;
610 case V42BIS_COMPRESSION_MODE_NEVER:
611 s->compress.change_transparency = 1;
612 break;
613 }
614 }
615 /*- End of function --------------------------------------------------------*/
616
617 SPAN_DECLARE(v42bis_state_t *) v42bis_init(v42bis_state_t *s,
618 int negotiated_p0,
619 int negotiated_p1,
620 int negotiated_p2,
621 v42bis_frame_handler_t frame_handler,
622 void *frame_user_data,
623 int max_frame_len,
624 v42bis_data_handler_t data_handler,
625 void *data_user_data,
626 int max_data_len)
627 {
628 int i;
629
630 if (negotiated_p1 < 512 || negotiated_p1 > 65535)
631 return NULL;
632 if (negotiated_p2 < 6 || negotiated_p2 > V42BIS_MAX_STRING_SIZE)
633 return NULL;
634 if (s == NULL)
635 {
636 if ((s = (v42bis_state_t *) malloc(sizeof(*s))) == NULL)
637 return NULL;
638 }
639 memset(s, 0, sizeof(*s));
640
641 s->compress.handler = frame_handler;
642 s->compress.user_data = frame_user_data;
643 s->compress.max_len = (max_frame_len < 1024) ? max_frame_len : 1024;
644
645 s->decompress.handler = data_handler;
646 s->decompress.user_data = data_user_data;
647 s->decompress.max_len = (max_data_len < 1024) ? max_data_len : 1024;
648
649 s->v42bis_parm_p0 = negotiated_p0; /* default is both ways off */
650
651 s->v42bis_parm_n1 = top_bit(negotiated_p1 - 1) + 1;
652 s->v42bis_parm_n2 = negotiated_p1;
653 s->v42bis_parm_n7 = negotiated_p2;
654
655 /* 6.5 */
656 s->compress.v42bis_parm_c1 =
657 s->decompress.v42bis_parm_c1 = V42BIS_N5;
658
659 s->compress.v42bis_parm_c2 =
660 s->decompress.v42bis_parm_c2 = V42BIS_N3 + 1;
661
662 s->compress.v42bis_parm_c3 =
663 s->decompress.v42bis_parm_c3 = 2*V42BIS_N4;
664
665 s->compress.first =
666 s->decompress.first = TRUE;
667 for (i = 0; i < V42BIS_MAX_CODEWORDS; i++)
668 {
669 s->compress.dict[i].parent_code =
670 s->decompress.dict[i].parent_code = 0xFFFF;
671 s->compress.dict[i].leaves =
672 s->decompress.dict[i].leaves = 0;
673 }
674 /* Point the root nodes for decompression to themselves. It doesn't matter much what
675 they are set to, as long as they are considered "known" codes. */
676 for (i = 0; i < V42BIS_N5; i++)
677 s->decompress.dict[i].parent_code = (uint16_t) i;
678 s->compress.string_code = 0xFFFFFFFF;
679 s->compress.latest_code = 0xFFFFFFFF;
680
681 s->decompress.last_old_code = 0xFFFFFFFF;
682 s->decompress.last_extra_octet = -1;
683
684 s->compress.compression_mode = V42BIS_COMPRESSION_MODE_DYNAMIC;
685
686 return s;
687 }
688 /*- End of function --------------------------------------------------------*/
689
690 SPAN_DECLARE(int) v42bis_release(v42bis_state_t *s)
691 {
692 return 0;
693 }
694 /*- End of function --------------------------------------------------------*/
695
696 SPAN_DECLARE(int) v42bis_free(v42bis_state_t *s)
697 {
698 free(s);
699 return 0;
700 }
701 /*- End of function --------------------------------------------------------*/
702 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.