diff options
Diffstat (limited to 'xdelta3/xdelta3-decode.h')
-rw-r--r-- | xdelta3/xdelta3-decode.h | 181 |
1 files changed, 102 insertions, 79 deletions
diff --git a/xdelta3/xdelta3-decode.h b/xdelta3/xdelta3-decode.h index bb03c04..5ddf823 100644 --- a/xdelta3/xdelta3-decode.h +++ b/xdelta3/xdelta3-decode.h | |||
@@ -20,19 +20,21 @@ | |||
20 | #define _XDELTA3_DECODE_H_ | 20 | #define _XDELTA3_DECODE_H_ |
21 | 21 | ||
22 | 22 | ||
23 | /* Return true if the caller must provide a source. Theoretically, this has to be checked | 23 | /* Return true if the caller must provide a source. Theoretically, |
24 | * after every window. It could be that the first window requires no source, but the | 24 | * this has to be checked after every window. It could be that the |
25 | * second window does. In practice? */ | 25 | * first window requires no source, but the second window does. In |
26 | * practice? */ | ||
26 | int xd3_decoder_needs_source (xd3_stream *stream) | 27 | int xd3_decoder_needs_source (xd3_stream *stream) |
27 | { | 28 | { |
28 | return stream->dec_win_ind & VCD_SOURCE; | 29 | return stream->dec_win_ind & VCD_SOURCE; |
29 | } | 30 | } |
30 | 31 | ||
31 | /* Initialize the decoder for a new window. The dec_tgtlen value is preserved across | 32 | /* Initialize the decoder for a new window. The dec_tgtlen value is |
32 | * successive window decodings, and the update to dec_winstart is delayed until a new | 33 | * preserved across successive window decodings, and the update to |
33 | * window actually starts. This is to avoid throwing an error due to overflow until the | 34 | * dec_winstart is delayed until a new window actually starts. This |
34 | * last possible moment. This makes it possible to encode exactly 4GB through a 32-bit | 35 | * is to avoid throwing an error due to overflow until the last |
35 | * encoder. */ | 36 | * possible moment. This makes it possible to encode exactly 4GB |
37 | * through a 32-bit encoder. */ | ||
36 | static int | 38 | static int |
37 | xd3_decode_init_window (xd3_stream *stream) | 39 | xd3_decode_init_window (xd3_stream *stream) |
38 | { | 40 | { |
@@ -45,25 +47,28 @@ xd3_decode_init_window (xd3_stream *stream) | |||
45 | return 0; | 47 | return 0; |
46 | } | 48 | } |
47 | 49 | ||
48 | /* Allocates buffer space for the target window and possibly the VCD_TARGET copy-window. | 50 | /* Allocates buffer space for the target window and possibly the |
49 | * Also sets the base of the two copy segments. */ | 51 | * VCD_TARGET copy-window. Also sets the base of the two copy |
52 | * segments. */ | ||
50 | static int | 53 | static int |
51 | xd3_decode_setup_buffers (xd3_stream *stream) | 54 | xd3_decode_setup_buffers (xd3_stream *stream) |
52 | { | 55 | { |
53 | /* If VCD_TARGET is set then the previous buffer may be reused. */ | 56 | /* If VCD_TARGET is set then the previous buffer may be reused. */ |
54 | if (stream->dec_win_ind & VCD_TARGET) | 57 | if (stream->dec_win_ind & VCD_TARGET) |
55 | { | 58 | { |
56 | /* But this implementation only supports copying from the last target window. If the | 59 | /* But this implementation only supports copying from the last |
57 | * offset is outside that range, it can't be done. */ | 60 | * target window. If the offset is outside that range, it can't |
61 | * be done. */ | ||
58 | if (stream->dec_cpyoff < stream->dec_laststart) | 62 | if (stream->dec_cpyoff < stream->dec_laststart) |
59 | { | 63 | { |
60 | stream->msg = "unsupported VCD_TARGET offset"; | 64 | stream->msg = "unsupported VCD_TARGET offset"; |
61 | return XD3_INVALID_INPUT; | 65 | return XD3_INVALID_INPUT; |
62 | } | 66 | } |
63 | 67 | ||
64 | /* See if the two windows are the same. This indicates the first time VCD_TARGET is | 68 | /* See if the two windows are the same. This indicates the |
65 | * used. This causes a second buffer to be allocated, after that the two are | 69 | * first time VCD_TARGET is used. This causes a second buffer |
66 | * swapped in the DEC_FINISH case. */ | 70 | * to be allocated, after that the two are swapped in the |
71 | * DEC_FINISH case. */ | ||
67 | if (stream->dec_lastwin == stream->next_out) | 72 | if (stream->dec_lastwin == stream->next_out) |
68 | { | 73 | { |
69 | stream->next_out = NULL; | 74 | stream->next_out = NULL; |
@@ -88,9 +93,10 @@ xd3_decode_setup_buffers (xd3_stream *stream) | |||
88 | stream->next_out = stream->dec_buffer; | 93 | stream->next_out = stream->dec_buffer; |
89 | } | 94 | } |
90 | 95 | ||
91 | /* dec_tgtaddrbase refers to an invalid base address, but it is always used with a | 96 | /* dec_tgtaddrbase refers to an invalid base address, but it is |
92 | * sufficiently large instruction offset (i.e., beyond the copy window). This condition | 97 | * always used with a sufficiently large instruction offset (i.e., |
93 | * is enforced by xd3_decode_output_halfinst. */ | 98 | * beyond the copy window). This condition is enforced by |
99 | * xd3_decode_output_halfinst. */ | ||
94 | stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; | 100 | stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; |
95 | 101 | ||
96 | return 0; | 102 | return 0; |
@@ -190,9 +196,10 @@ xd3_decode_section (xd3_stream *stream, | |||
190 | return 0; | 196 | return 0; |
191 | } | 197 | } |
192 | 198 | ||
193 | /* Decode the size and address for half of an instruction (i.e., a single opcode). This | 199 | /* Decode the size and address for half of an instruction (i.e., a |
194 | * updates the stream->dec_position, which are bytes already output prior to processing | 200 | * single opcode). This updates the stream->dec_position, which are |
195 | * this instruction. Perform bounds checking for sizes and copy addresses, which uses the | 201 | * bytes already output prior to processing this instruction. Perform |
202 | * bounds checking for sizes and copy addresses, which uses the | ||
196 | * dec_position (which is why these checks are done here). */ | 203 | * dec_position (which is why these checks are done here). */ |
197 | static int | 204 | static int |
198 | xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) | 205 | xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) |
@@ -303,9 +310,10 @@ xd3_decode_instruction (xd3_stream *stream) | |||
303 | stream->dec_current1.size = inst->size1; | 310 | stream->dec_current1.size = inst->size1; |
304 | stream->dec_current2.size = inst->size2; | 311 | stream->dec_current2.size = inst->size2; |
305 | 312 | ||
306 | /* For each instruction with a real operation, decode the corresponding size and | 313 | /* For each instruction with a real operation, decode the |
307 | * addresses if necessary. Assume a code-table may have NOOP in either position, | 314 | * corresponding size and addresses if necessary. Assume a |
308 | * although this is unlikely. */ | 315 | * code-table may have NOOP in either position, although this is |
316 | * unlikely. */ | ||
309 | if (inst->type1 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) | 317 | if (inst->type1 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) |
310 | { | 318 | { |
311 | return ret; | 319 | return ret; |
@@ -317,11 +325,13 @@ xd3_decode_instruction (xd3_stream *stream) | |||
317 | return 0; | 325 | return 0; |
318 | } | 326 | } |
319 | 327 | ||
320 | /* Output the result of a single half-instruction. OPT: This the decoder hotspot. */ | 328 | /* Output the result of a single half-instruction. OPT: This the |
329 | decoder hotspot. */ | ||
321 | static int | 330 | static int |
322 | xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | 331 | xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) |
323 | { | 332 | { |
324 | /* To make this reentrant, set take = min (inst->size, available space)... */ | 333 | /* To make this reentrant, set take = min (inst->size, available |
334 | space)... */ | ||
325 | usize_t take = inst->size; | 335 | usize_t take = inst->size; |
326 | 336 | ||
327 | XD3_ASSERT (inst->type != XD3_NOOP); | 337 | XD3_ASSERT (inst->type != XD3_NOOP); |
@@ -370,14 +380,15 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
370 | const uint8_t *src; | 380 | const uint8_t *src; |
371 | uint8_t *dst; | 381 | uint8_t *dst; |
372 | 382 | ||
373 | /* See if it copies from the VCD_TARGET/VCD_SOURCE window or the target window. | 383 | /* See if it copies from the VCD_TARGET/VCD_SOURCE window or |
374 | * Out-of-bounds checks for the addresses and sizes are performed in | 384 | * the target window. Out-of-bounds checks for the addresses |
375 | * xd3_decode_parse_halfinst. */ | 385 | * and sizes are performed in xd3_decode_parse_halfinst. */ |
376 | if (inst->addr < stream->dec_cpylen) | 386 | if (inst->addr < stream->dec_cpylen) |
377 | { | 387 | { |
378 | if (stream->dec_win_ind & VCD_TARGET) | 388 | if (stream->dec_win_ind & VCD_TARGET) |
379 | { | 389 | { |
380 | /* For VCD_TARGET we know the entire range is in-memory, as established by | 390 | /* For VCD_TARGET we know the entire range is |
391 | * in-memory, as established by | ||
381 | * decode_setup_buffers. */ | 392 | * decode_setup_buffers. */ |
382 | src = stream->dec_cpyaddrbase + inst->addr; | 393 | src = stream->dec_cpyaddrbase + inst->addr; |
383 | inst->type = XD3_NOOP; | 394 | inst->type = XD3_NOOP; |
@@ -385,8 +396,9 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
385 | } | 396 | } |
386 | else | 397 | else |
387 | { | 398 | { |
388 | /* In this case we have to read a source block, which could return control | 399 | /* In this case we have to read a source block, which |
389 | * to the caller. We need to know the first block number needed for this | 400 | * could return control to the caller. We need to |
401 | * know the first block number needed for this | ||
390 | * copy. */ | 402 | * copy. */ |
391 | xd3_source *source; | 403 | xd3_source *source; |
392 | xoff_t block; | 404 | xoff_t block; |
@@ -419,8 +431,8 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
419 | 431 | ||
420 | src = source->curblk + blkoff; | 432 | src = source->curblk + blkoff; |
421 | 433 | ||
422 | /* This block either contains enough data or the source file is | 434 | /* This block either contains enough data or the |
423 | * short. */ | 435 | * source file is short. */ |
424 | if ((source->onblk != blksize) && (blkoff + take > source->onblk)) | 436 | if ((source->onblk != blksize) && (blkoff + take > source->onblk)) |
425 | { | 437 | { |
426 | stream->msg = "source file too short"; | 438 | stream->msg = "source file too short"; |
@@ -437,8 +449,8 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
437 | } | 449 | } |
438 | else | 450 | else |
439 | { | 451 | { |
440 | /* This block doesn't contain all the data, modify the instruction, do | 452 | /* This block doesn't contain all the data, modify |
441 | * not set to XD3_NOOP. */ | 453 | * the instruction, do not set to XD3_NOOP. */ |
442 | take = blksize - blkoff; | 454 | take = blksize - blkoff; |
443 | inst->size -= take; | 455 | inst->size -= take; |
444 | inst->addr += take; | 456 | inst->addr += take; |
@@ -447,9 +459,10 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
447 | } | 459 | } |
448 | else | 460 | else |
449 | { | 461 | { |
450 | /* For a target-window copy, we know the entire range is in-memory. The | 462 | /* For a target-window copy, we know the entire range is |
451 | * dec_tgtaddrbase is negatively offset by dec_cpylen because the addresses | 463 | * in-memory. The dec_tgtaddrbase is negatively offset by |
452 | * start beyond that point. */ | 464 | * dec_cpylen because the addresses start beyond that |
465 | * point. */ | ||
453 | src = stream->dec_tgtaddrbase + inst->addr; | 466 | src = stream->dec_tgtaddrbase + inst->addr; |
454 | inst->type = XD3_NOOP; | 467 | inst->type = XD3_NOOP; |
455 | inst->size = 0; | 468 | inst->size = 0; |
@@ -587,9 +600,10 @@ xd3_decode_sections (xd3_stream *stream) | |||
587 | return xd3_decode_finish_window (stream); | 600 | return xd3_decode_finish_window (stream); |
588 | } | 601 | } |
589 | 602 | ||
590 | /* OPT: A possible optimization is to avoid allocating memory in decode_setup_buffers | 603 | /* OPT: A possible optimization is to avoid allocating memory in |
591 | * and to avoid a large memcpy when the window consists of a single VCD_SOURCE copy | 604 | * decode_setup_buffers and to avoid a large memcpy when the window |
592 | * instruction. The only potential problem is if the following window is a VCD_TARGET, | 605 | * consists of a single VCD_SOURCE copy instruction. The only |
606 | * potential problem is if the following window is a VCD_TARGET, | ||
593 | * then you need to remember... */ | 607 | * then you need to remember... */ |
594 | if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } | 608 | if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } |
595 | 609 | ||
@@ -601,14 +615,16 @@ xd3_decode_emit (xd3_stream *stream) | |||
601 | { | 615 | { |
602 | int ret; | 616 | int ret; |
603 | 617 | ||
604 | /* Produce output: originally structured to allow reentrant code that fills as much of | 618 | /* Produce output: originally structured to allow reentrant code |
605 | * the output buffer as possible, but VCDIFF semantics allows to copy from anywhere from | 619 | * that fills as much of the output buffer as possible, but VCDIFF |
606 | * the target window, so instead allocate a sufficiently sized buffer after the target | 620 | * semantics allows to copy from anywhere from the target window, so |
621 | * instead allocate a sufficiently sized buffer after the target | ||
607 | * window length is decoded. | 622 | * window length is decoded. |
608 | * | 623 | * |
609 | * This code still needs to be reentrant to allow XD3_GETSRCBLK to return control. This | 624 | * This code still needs to be reentrant to allow XD3_GETSRCBLK to |
610 | * is handled by setting the stream->dec_currentN instruction types to XD3_NOOP after | 625 | * return control. This is handled by setting the |
611 | * they have been processed. */ | 626 | * stream->dec_currentN instruction types to XD3_NOOP after they |
627 | * have been processed. */ | ||
612 | XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); | 628 | XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); |
613 | XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); | 629 | XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); |
614 | 630 | ||
@@ -683,35 +699,39 @@ xd3_decode_input (xd3_stream *stream) | |||
683 | return XD3_INVALID_INPUT; | 699 | return XD3_INVALID_INPUT; |
684 | } | 700 | } |
685 | 701 | ||
686 | #define BYTE_CASE(expr,x,nstate) \ | 702 | #define BYTE_CASE(expr,x,nstate) \ |
687 | do { \ | 703 | do { \ |
688 | if ( (expr) && \ | 704 | if ( (expr) && \ |
689 | ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ | 705 | ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ |
690 | stream->dec_state = (nstate); \ | 706 | stream->dec_state = (nstate); \ |
691 | } while (0) | 707 | } while (0) |
692 | 708 | ||
693 | #define OFFSET_CASE(expr,x,nstate) \ | 709 | #define OFFSET_CASE(expr,x,nstate) \ |
694 | do { \ | 710 | do { \ |
695 | if ( (expr) && \ | 711 | if ( (expr) && \ |
696 | ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ | 712 | ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ |
697 | stream->dec_state = (nstate); \ | 713 | stream->dec_state = (nstate); \ |
698 | } while (0) | 714 | } while (0) |
699 | 715 | ||
700 | #define SIZE_CASE(expr,x,nstate) \ | 716 | #define SIZE_CASE(expr,x,nstate) \ |
701 | do { \ | 717 | do { \ |
702 | if ( (expr) && \ | 718 | if ( (expr) && \ |
703 | ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ | 719 | ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ |
704 | stream->dec_state = (nstate); \ | 720 | stream->dec_state = (nstate); \ |
705 | } while (0) | 721 | } while (0) |
706 | 722 | ||
707 | #define SRCORTGT(x) (((x) & VCD_SRCORTGT) == VCD_SOURCE || \ | 723 | #define SRCORTGT(x) (((x) & VCD_SRCORTGT) == VCD_SOURCE || \ |
708 | ((x) & VCD_SRCORTGT) == VCD_TARGET) | 724 | ((x) & VCD_SRCORTGT) == VCD_TARGET) |
709 | 725 | ||
710 | switch (stream->dec_state) | 726 | switch (stream->dec_state) |
711 | { | 727 | { |
712 | case DEC_VCHEAD: | 728 | case DEC_VCHEAD: |
713 | { | 729 | { |
714 | if ((ret = xd3_decode_bytes (stream, stream->dec_magic, & stream->dec_magicbytes, 4))) { return ret; } | 730 | if ((ret = xd3_decode_bytes (stream, stream->dec_magic, |
731 | & stream->dec_magicbytes, 4))) | ||
732 | { | ||
733 | return ret; | ||
734 | } | ||
715 | 735 | ||
716 | if (stream->dec_magic[0] != VCDIFF_MAGIC1 || | 736 | if (stream->dec_magic[0] != VCDIFF_MAGIC1 || |
717 | stream->dec_magic[1] != VCDIFF_MAGIC2 || | 737 | stream->dec_magic[1] != VCDIFF_MAGIC2 || |
@@ -817,7 +837,8 @@ xd3_decode_input (xd3_stream *stream) | |||
817 | /* Application data */ | 837 | /* Application data */ |
818 | if (stream->dec_hdr_ind & VCD_APPHEADER) | 838 | if (stream->dec_hdr_ind & VCD_APPHEADER) |
819 | { | 839 | { |
820 | /* Note: we add an additional byte for padding, to allow 0-termination. */ | 840 | /* Note: we add an additional byte for padding, to allow |
841 | 0-termination. */ | ||
821 | if ((stream->dec_appheader == NULL) && | 842 | if ((stream->dec_appheader == NULL) && |
822 | (stream->dec_appheader = xd3_alloc (stream, stream->dec_appheadsz+1, 1)) == NULL) { return ENOMEM; } | 843 | (stream->dec_appheader = xd3_alloc (stream, stream->dec_appheadsz+1, 1)) == NULL) { return ENOMEM; } |
823 | 844 | ||
@@ -865,9 +886,10 @@ xd3_decode_input (xd3_stream *stream) | |||
865 | /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ | 886 | /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ |
866 | SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, DEC_CPYOFF); | 887 | SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, DEC_CPYOFF); |
867 | 888 | ||
868 | /* Set the initial, logical decoder position (HERE address) in dec_position. This | 889 | /* Set the initial, logical decoder position (HERE address) in |
869 | * is set to just after the source/copy window, as we are just about to output the | 890 | * dec_position. This is set to just after the source/copy |
870 | * first byte of target window. */ | 891 | * window, as we are just about to output the first byte of |
892 | * target window. */ | ||
871 | stream->dec_position = stream->dec_cpylen; | 893 | stream->dec_position = stream->dec_cpylen; |
872 | 894 | ||
873 | case DEC_CPYOFF: | 895 | case DEC_CPYOFF: |
@@ -881,7 +903,8 @@ xd3_decode_input (xd3_stream *stream) | |||
881 | return XD3_INVALID_INPUT; | 903 | return XD3_INVALID_INPUT; |
882 | } | 904 | } |
883 | 905 | ||
884 | /* Check copy window bounds: VCD_TARGET window may not exceed current position. */ | 906 | /* Check copy window bounds: VCD_TARGET window may not exceed |
907 | current position. */ | ||
885 | if ((stream->dec_win_ind & VCD_TARGET) && | 908 | if ((stream->dec_win_ind & VCD_TARGET) && |
886 | (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > stream->dec_winstart)) | 909 | (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > stream->dec_winstart)) |
887 | { | 910 | { |
@@ -896,9 +919,9 @@ xd3_decode_input (xd3_stream *stream) | |||
896 | /* Length of target window */ | 919 | /* Length of target window */ |
897 | SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); | 920 | SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); |
898 | 921 | ||
899 | /* Set the maximum decoder position, beyond which we should not decode any data. | 922 | /* Set the maximum decoder position, beyond which we should not |
900 | * This is the maximum value for dec_position. This may not exceed the size of a | 923 | * decode any data. This is the maximum value for dec_position. |
901 | * usize_t. */ | 924 | * This may not exceed the size of a usize_t. */ |
902 | if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) | 925 | if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) |
903 | { | 926 | { |
904 | stream->msg = "decoder target window overflows a usize_t"; | 927 | stream->msg = "decoder target window overflows a usize_t"; |
@@ -973,8 +996,8 @@ xd3_decode_input (xd3_stream *stream) | |||
973 | } | 996 | } |
974 | } | 997 | } |
975 | 998 | ||
976 | /* Returning here gives the application a chance to inspect the header, skip the | 999 | /* Returning here gives the application a chance to inspect the |
977 | * window, etc. */ | 1000 | * header, skip the window, etc. */ |
978 | if (stream->current_window == 0) { return XD3_GOTHEADER; } | 1001 | if (stream->current_window == 0) { return XD3_GOTHEADER; } |
979 | else { return XD3_WINSTART; } | 1002 | else { return XD3_WINSTART; } |
980 | 1003 | ||
@@ -986,8 +1009,8 @@ xd3_decode_input (xd3_stream *stream) | |||
986 | 1009 | ||
987 | case DEC_EMIT: | 1010 | case DEC_EMIT: |
988 | 1011 | ||
989 | /* To speed VCD_SOURCE block-address calculations, the source cpyoff_blocks and | 1012 | /* To speed VCD_SOURCE block-address calculations, the source |
990 | * cpyoff_blkoff are pre-computed. */ | 1013 | * cpyoff_blocks and cpyoff_blkoff are pre-computed. */ |
991 | if (stream->dec_win_ind & VCD_SOURCE) | 1014 | if (stream->dec_win_ind & VCD_SOURCE) |
992 | { | 1015 | { |
993 | xd3_source *src = stream->src; | 1016 | xd3_source *src = stream->src; |
@@ -1030,8 +1053,8 @@ xd3_decode_input (xd3_stream *stream) | |||
1030 | stream->dec_laststart = stream->dec_winstart; | 1053 | stream->dec_laststart = stream->dec_winstart; |
1031 | stream->dec_window_count += 1; | 1054 | stream->dec_window_count += 1; |
1032 | 1055 | ||
1033 | /* Note: the updates to dec_winstart & current_window are deferred until after the | 1056 | /* Note: the updates to dec_winstart & current_window are |
1034 | * next DEC_WININD byte is read. */ | 1057 | * deferred until after the next DEC_WININD byte is read. */ |
1035 | stream->dec_state = DEC_WININD; | 1058 | stream->dec_state = DEC_WININD; |
1036 | return XD3_WINFINISH; | 1059 | return XD3_WINFINISH; |
1037 | } | 1060 | } |