Added write_ndx() and read_ndx(), functions that allow us to transmit
authorWayne Davison <wayned@samba.org>
Thu, 28 Dec 2006 18:49:08 +0000 (18:49 +0000)
committerWayne Davison <wayned@samba.org>
Thu, 28 Dec 2006 18:49:08 +0000 (18:49 +0000)
fewer bytes when exchanging the file-list index values.

io.c

diff --git a/io.c b/io.c
index 3ad9147..e2304d4 100644 (file)
--- 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