From 8a65e0ce00bb5150c1cc70b985a649e0dc9e5278 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Thu, 28 Dec 2006 18:49:08 +0000 Subject: [PATCH] Added write_ndx() and read_ndx(), functions that allow us to transmit fewer bytes when exchanging the file-list index values. --- io.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/io.c b/io.c index 3ad91472..e2304d4f 100644 --- a/io.c +++ b/io.c @@ -1543,6 +1543,86 @@ void write_vstring(int f, const char *str, int len) writefd(f, str, len); } +/* Send a file-list index using a byte-reduction method. */ +void write_ndx(int f, int32 ndx) +{ + static int32 prev_positive = -1, prev_negative = 1; + int32 diff, cnt = 0; + char b[6]; + + if (protocol_version < 30 || read_batch) { + write_int(f, ndx); + return; + } + + /* Send NDX_DONE as a single-byte 0 with no side effects. Send + * negative nums as a positive after sending a leading 0xFF. */ + if (ndx >= 0) { + diff = ndx - prev_positive; + prev_positive = ndx; + } else if (ndx == NDX_DONE) { + *b = 0; + writefd(f, b, 1); + return; + } else { + b[cnt++] = (char)0xFF; + ndx = -ndx; + diff = ndx - prev_negative; + prev_negative = ndx; + } + + /* A diff of 1 - 253 is sent as a one-byte diff; a diff of 254 - 32767 + * or 0 is sent as a 0xFE + a two-byte diff; otherwise we send 0xFE + * & all 4 bytes of the (non-negative) num with the high-bit set. */ + if (diff < 0xFE && diff > 0) + b[cnt++] = (char)diff; + else if (diff < 0 || diff > 0x7FFF) { + b[cnt++] = (char)0xFE; + b[cnt++] = (char)((ndx >> 24) | 0x80); + b[cnt++] = (char)(ndx >> 16); + b[cnt++] = (char)(ndx >> 8); + b[cnt++] = (char)ndx; + } else { + b[cnt++] = (char)0xFE; + b[cnt++] = (char)(diff >> 8); + b[cnt++] = (char)diff; + } + writefd(f, b, cnt); +} + +/* Receive a file-list index using a byte-reduction method. */ +int32 read_ndx(int f) +{ + static int32 prev_positive = -1, prev_negative = 1; + int32 *prev_ptr, num; + char b[4]; + + if (protocol_version < 30) + return read_int(f); + + readfd(f, b, 1); + if (CVAL(b, 0) == 0xFF) { + readfd(f, b, 1); + prev_ptr = &prev_negative; + } else if (CVAL(b, 0) == 0) + return NDX_DONE; + else + prev_ptr = &prev_positive; + if (CVAL(b, 0) == 0xFE) { + readfd(f, b, 2); + if (CVAL(b, 0) & 0x80) { + readfd(f, b+2, 2); + num = NVAL4(b, 0x80); + } else + num = NVAL2(b, 0) + *prev_ptr; + } else + num = CVAL(b, 0) + *prev_ptr; + *prev_ptr = num; + if (prev_ptr == &prev_negative) + num = -num; + return num; +} + /** * Read a line of up to @p maxlen characters into @p buf (not counting * the trailing null). Strips the (required) trailing newline and all -- 2.34.1