summaryrefslogtreecommitdiff
path: root/xdelta3/xdelta3.c
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2007-02-01 09:17:19 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2007-02-01 09:17:19 +0000
commit8748d16e6e5bf741ede89af1940f8291fb1b8046 (patch)
tree2c9d393e21eb669ae6bdecf931331e1202bffec6 /xdelta3/xdelta3.c
parent9f465a9db201b97c43d69778eabd222d4fc09fd5 (diff)
Implmeent xd3_encode_memory() and xd3_decode_memory(), add comments.
Diffstat (limited to 'xdelta3/xdelta3.c')
-rwxr-xr-xxdelta3/xdelta3.c186
1 files changed, 143 insertions, 43 deletions
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index aaea811..5740777 100755
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -763,9 +763,7 @@ static const xd3_sec_type djw_sec_type =
763 * allowing to vary the distribution of single- and 763 * allowing to vary the distribution of single- and
764 * double-instructions and change the number of near and same copy 764 * double-instructions and change the number of near and same copy
765 * modes. More exotic tables are only possible by extending this 765 * modes. More exotic tables are only possible by extending this
766 * code, but a detailed experiment would need to be carried out first, 766 * code. TODO: experiment with a double-copy instruction.
767 * probably using separate code. I would like to experiment with a
768 * double-copy instruction, for example.
769 * 767 *
770 * For performance reasons, both the parametrized and non-parametrized 768 * For performance reasons, both the parametrized and non-parametrized
771 * versions of xd3_choose_instruction remain. The parametrized 769 * versions of xd3_choose_instruction remain. The parametrized
@@ -1209,8 +1207,8 @@ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *cod
1209 1207
1210 if ((ret = xd3_set_source (& stream, & source))) { goto fail; } 1208 if ((ret = xd3_set_source (& stream, & source))) { goto fail; }
1211 1209
1212 if ((ret = xd3_encode_completely_stream (& stream, code_string, CODE_TABLE_STRING_SIZE, 1210 if ((ret = xd3_encode_stream (& stream, code_string, CODE_TABLE_STRING_SIZE,
1213 comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE))) { goto fail; } 1211 comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE))) { goto fail; }
1214 1212
1215 fail: 1213 fail:
1216 1214
@@ -1405,7 +1403,7 @@ xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t si
1405 1403
1406 if ((ret = xd3_config_stream (& stream, NULL)) || 1404 if ((ret = xd3_config_stream (& stream, NULL)) ||
1407 (ret = xd3_set_source (& stream, & source)) || 1405 (ret = xd3_set_source (& stream, & source)) ||
1408 (ret = xd3_decode_completely_stream (& stream, data, size, code_string, & code_size, sizeof (code_string)))) 1406 (ret = xd3_decode_stream (& stream, data, size, code_string, & code_size, sizeof (code_string))))
1409 { 1407 {
1410 in_stream->msg = stream.msg; 1408 in_stream->msg = stream.msg;
1411 goto fail; 1409 goto fail;
@@ -3809,17 +3807,15 @@ xd3_encode_input (xd3_stream *stream)
3809 Client convenience functions 3807 Client convenience functions
3810 ******************************************************************************************/ 3808 ******************************************************************************************/
3811 3809
3812/* This function invokes either encode or decode to and from in-memory arrays. The output array
3813 * must be large enough to hold the output or else ENOSPC is returned. */
3814static int 3810static int
3815xd3_process_completely_stream (xd3_stream *stream, 3811xd3_process_stream (xd3_stream *stream,
3816 int (*func) (xd3_stream *), 3812 int (*func) (xd3_stream *),
3817 int close_stream, 3813 int close_stream,
3818 const uint8_t *input, 3814 const uint8_t *input,
3819 usize_t input_size, 3815 usize_t input_size,
3820 uint8_t *output, 3816 uint8_t *output,
3821 usize_t *output_size, 3817 usize_t *output_size,
3822 usize_t avail_size) 3818 usize_t output_size_max)
3823{ 3819{
3824 (*output_size) = 0; 3820 (*output_size) = 0;
3825 3821
@@ -3842,13 +3838,17 @@ xd3_process_completely_stream (xd3_stream *stream,
3842 stream->msg = "stream requires source input"; 3838 stream->msg = "stream requires source input";
3843 return XD3_INTERNAL; 3839 return XD3_INTERNAL;
3844 } 3840 }
3845 case 0: /* there is no plain "success" return for xd3_encode/decode */ 3841 case 0:
3846 XD3_ASSERT (ret != 0); 3842 {
3843 /* xd3_encode_input/xd3_decode_input never return 0 */
3844 stream->msg = "invalid return: 0";
3845 return XD3_INTERNAL;
3846 }
3847 default: 3847 default:
3848 return ret; 3848 return ret;
3849 } 3849 }
3850 3850
3851 if (*output_size + stream->avail_out > avail_size) 3851 if (*output_size + stream->avail_out > output_size_max)
3852 { 3852 {
3853 stream->msg = "insufficient output space"; 3853 stream->msg = "insufficient output space";
3854 return ENOSPC; 3854 return ENOSPC;
@@ -3864,34 +3864,129 @@ xd3_process_completely_stream (xd3_stream *stream,
3864 return (close_stream == 0) ? 0 : xd3_close_stream (stream); 3864 return (close_stream == 0) ? 0 : xd3_close_stream (stream);
3865} 3865}
3866 3866
3867static int
3868xd3_process_memory (int (*func) (xd3_stream *),
3869 int close_stream,
3870 const uint8_t *input,
3871 usize_t input_size,
3872 const uint8_t *source,
3873 usize_t source_size,
3874 uint8_t *output,
3875 usize_t *output_size,
3876 usize_t output_size_max,
3877 int flags) {
3878 xd3_stream stream;
3879 xd3_config config;
3880 xd3_source src;
3881 int ret;
3882
3883 /* TODO: for small inputs, the xd3_stream could be configured to allocate MUCH less
3884 * memory. Most of the allocations sizes are defaulted (see xdelta3.h), and assume
3885 * large inputs. */
3886 memset (& stream, 0, sizeof (stream));
3887 memset (& config, 0, sizeof (config));
3888
3889 config.flags = flags;
3890 config.srcwin_maxsz = source_size;
3891 config.winsize = input_size;
3892
3893 if ((ret = xd3_config_stream (&stream, &config)) != 0)
3894 {
3895 goto exit;
3896 }
3897
3898 if (source != NULL)
3899 {
3900 memset (& src, 0, sizeof (src));
3901 src.size = source_size;
3902 src.blksize = source_size;
3903 src.onblk = source_size;
3904 src.curblk = source;
3905 src.curblkno = 0;
3906
3907 if ((ret = xd3_set_source (&stream, &src)) != 0)
3908 {
3909 goto exit;
3910 }
3911 }
3912
3913 if ((ret = xd3_process_stream (& stream,
3914 func, 1,
3915 input, input_size,
3916 output,
3917 output_size,
3918 output_size_max)) != 0)
3919 {
3920 goto exit;
3921 }
3922
3923 exit:
3924 xd3_free_stream(&stream);
3925 return ret;
3926}
3927
3867int 3928int
3868xd3_decode_completely_stream (xd3_stream *stream, 3929xd3_decode_stream (xd3_stream *stream,
3869 const uint8_t *input, 3930 const uint8_t *input,
3870 usize_t input_size, 3931 usize_t input_size,
3871 uint8_t *output, 3932 uint8_t *output,
3872 usize_t *output_size, 3933 usize_t *output_size,
3873 usize_t avail_size) 3934 usize_t output_size_max)
3874{ 3935{
3875 return xd3_process_completely_stream (stream, & xd3_decode_input, 1, 3936 return xd3_process_stream (stream, & xd3_decode_input, 1,
3876 input, input_size, 3937 input, input_size,
3877 output, output_size, avail_size); 3938 output, output_size, output_size_max);
3878} 3939}
3879 3940
3941int
3942xd3_decode_memory (const uint8_t *input,
3943 usize_t input_size,
3944 const uint8_t *source,
3945 usize_t source_size,
3946 uint8_t *output,
3947 usize_t *output_size,
3948 usize_t output_size_max,
3949 int flags) {
3950 return xd3_process_memory (& xd3_decode_input, 1,
3951 input, input_size,
3952 source, source_size,
3953 output, output_size, output_size_max,
3954 flags);
3955}
3956
3957
3880#if XD3_ENCODER 3958#if XD3_ENCODER
3881int 3959int
3882xd3_encode_completely_stream (xd3_stream *stream, 3960xd3_encode_stream (xd3_stream *stream,
3883 const uint8_t *input, 3961 const uint8_t *input,
3884 usize_t input_size, 3962 usize_t input_size,
3885 uint8_t *output, 3963 uint8_t *output,
3886 usize_t *output_size, 3964 usize_t *output_size,
3887 usize_t avail_size) 3965 usize_t output_size_max)
3888{ 3966{
3889 return xd3_process_completely_stream (stream, & xd3_encode_input, 1, 3967 return xd3_process_stream (stream, & xd3_encode_input, 1,
3890 input, input_size, 3968 input, input_size,
3891 output, output_size, avail_size); 3969 output, output_size, output_size_max);
3970}
3971
3972int
3973xd3_encode_memory (const uint8_t *input,
3974 usize_t input_size,
3975 const uint8_t *source,
3976 usize_t source_size,
3977 uint8_t *output,
3978 usize_t *output_size,
3979 usize_t output_size_max,
3980 int flags) {
3981 return xd3_process_memory (& xd3_encode_input, 1,
3982 input, input_size,
3983 source, source_size,
3984 output, output_size, output_size_max,
3985 flags);
3892} 3986}
3893#endif 3987#endif
3894 3988
3989
3895/****************************************************************************************** 3990/******************************************************************************************
3896 String matching helpers 3991 String matching helpers
3897 ******************************************************************************************/ 3992 ******************************************************************************************/
@@ -3996,7 +4091,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
3996 stream->srcwin_cksum_pos = stream->maxsrcaddr; 4091 stream->srcwin_cksum_pos = stream->maxsrcaddr;
3997 } 4092 }
3998 4093
3999 if (logical_input_cksum_pos < stream->srcwin_cksum_pos) 4094 if (logical_input_cksum_pos < stream->srcwin_cksum_pos)
4000 { 4095 {
4001 logical_input_cksum_pos = stream->srcwin_cksum_pos; 4096 logical_input_cksum_pos = stream->srcwin_cksum_pos;
4002 } 4097 }
@@ -4004,7 +4099,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4004 /* Advance an extra srcwin_size bytes */ 4099 /* Advance an extra srcwin_size bytes */
4005 logical_input_cksum_pos += stream->srcwin_size; 4100 logical_input_cksum_pos += stream->srcwin_size;
4006 4101
4007 IF_DEBUG1 (P(RINT "[srcwin_move_point] T=%"Q"u S=%"Q"u/%"Q"u\n", 4102 IF_DEBUG1 (P(RINT "[srcwin_move_point] T=%"Q"u S=%"Q"u/%"Q"u\n",
4008 stream->total_in + stream->input_position, 4103 stream->total_in + stream->input_position,
4009 stream->srcwin_cksum_pos, 4104 stream->srcwin_cksum_pos,
4010 logical_input_cksum_pos)); 4105 logical_input_cksum_pos));
@@ -4038,6 +4133,9 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4038 diff = logical_input_cksum_pos - stream->srcwin_cksum_pos; 4133 diff = logical_input_cksum_pos - stream->srcwin_cksum_pos;
4039 onblk = min(blkoff + diff, onblk); 4134 onblk = min(blkoff + diff, onblk);
4040 4135
4136 /* TODO: This block needs to be included in the template pass... duh.
4137 */
4138
4041 /* Note: I experimented with rewriting this block to use LARGE_CKSUM_UPDATE() 4139 /* Note: I experimented with rewriting this block to use LARGE_CKSUM_UPDATE()
4042 * instead of recalculating the cksum every N bytes. It seemed to make performance 4140 * instead of recalculating the cksum every N bytes. It seemed to make performance
4043 * worse. */ 4141 * worse. */
@@ -4066,7 +4164,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4066 4164
4067/* This function handles the 32/64bit ambiguity -- file positions are 64bit but the hash 4165/* This function handles the 32/64bit ambiguity -- file positions are 64bit but the hash
4068 * table for source-offsets is 32bit. */ 4166 * table for source-offsets is 32bit. */
4069static xoff_t 4167static xoff_t
4070xd3_source_cksum_offset(xd3_stream *stream, usize_t low) 4168xd3_source_cksum_offset(xd3_stream *stream, usize_t low)
4071{ 4169{
4072 xoff_t scp = stream->srcwin_cksum_pos; 4170 xoff_t scp = stream->srcwin_cksum_pos;
@@ -4179,7 +4277,7 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos)
4179 greedy_or_not = stream->unencoded_offset; 4277 greedy_or_not = stream->unencoded_offset;
4180 } 4278 }
4181 4279
4182 4280
4183 4281
4184 /* Backward target match limit. */ 4282 /* Backward target match limit. */
4185 XD3_ASSERT (stream->input_position >= greedy_or_not); 4283 XD3_ASSERT (stream->input_position >= greedy_or_not);
@@ -4295,7 +4393,7 @@ xd3_source_extend_match (xd3_stream *stream)
4295 { 4393 {
4296 break; 4394 break;
4297 } 4395 }
4298 4396
4299 /* could be a XD3_GETSRCBLK failure. */ 4397 /* could be a XD3_GETSRCBLK failure. */
4300 return ret; 4398 return ret;
4301 } 4399 }
@@ -4387,7 +4485,7 @@ xd3_source_extend_match (xd3_stream *stream)
4387 4485
4388 /* Correct the variables to remove match_back from the equation. */ 4486 /* Correct the variables to remove match_back from the equation. */
4389 // IT'S A BUG! 4487 // IT'S A BUG!
4390 4488
4391 usize_t target_position = stream->input_position - stream->match_back; 4489 usize_t target_position = stream->input_position - stream->match_back;
4392 usize_t match_length = stream->match_back + stream->match_fwd; 4490 usize_t match_length = stream->match_back + stream->match_fwd;
4393 xoff_t match_position = stream->match_srcpos - stream->match_back; 4491 xoff_t match_position = stream->match_srcpos - stream->match_back;
@@ -4554,6 +4652,8 @@ xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0,
4554 * comparison to zlib) in order to support the PROMOTE decision, which is to prefer the 4652 * comparison to zlib) in order to support the PROMOTE decision, which is to prefer the
4555 * most recently used matching address of a certain string to aid the VCDIFF same cache. 4653 * most recently used matching address of a certain string to aid the VCDIFF same cache.
4556 * 4654 *
4655 * --- TODO: declare the PROMOTE experiment a failure -- remove the extra LIST --
4656 *
4557 * Weak reasoning? it's time to modularize this routine...? Let's say the PROMOTE 4657 * Weak reasoning? it's time to modularize this routine...? Let's say the PROMOTE
4558 * feature supported by this slow data structure contributes around 2% improvement in 4658 * feature supported by this slow data structure contributes around 2% improvement in
4559 * compressed size, is there a better code table that doesn't use the SAME address cache, 4659 * compressed size, is there a better code table that doesn't use the SAME address cache,