Code

diffcore-break: micro-optimize by avoiding delta between identical files.
[git.git] / pkt-line.c
1 #include "cache.h"
2 #include "pkt-line.h"
4 /*
5  * Write a packetized stream, where each line is preceded by
6  * its length (including the header) as a 4-byte hex number.
7  * A length of 'zero' means end of stream (and a length of 1-3
8  * would be an error). 
9  *
10  * This is all pretty stupid, but we use this packetized line
11  * format to make a streaming format possible without ever
12  * over-running the read buffers. That way we'll never read
13  * into what might be the pack data (which should go to another
14  * process entirely).
15  *
16  * The writing side could use stdio, but since the reading
17  * side can't, we stay with pure read/write interfaces.
18  */
19 static void safe_write(int fd, const void *buf, unsigned n)
20 {
21         while (n) {
22                 int ret = xwrite(fd, buf, n);
23                 if (ret > 0) {
24                         buf += ret;
25                         n -= ret;
26                         continue;
27                 }
28                 if (!ret)
29                         die("write error (disk full?)");
30                 die("write error (%s)", strerror(errno));
31         }
32 }
34 /*
35  * If we buffered things up above (we don't, but we should),
36  * we'd flush it here
37  */
38 void packet_flush(int fd)
39 {
40         safe_write(fd, "0000", 4);
41 }
43 #define hex(a) (hexchar[(a) & 15])
44 void packet_write(int fd, const char *fmt, ...)
45 {
46         static char buffer[1000];
47         static char hexchar[] = "0123456789abcdef";
48         va_list args;
49         unsigned n;
51         va_start(args, fmt);
52         n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
53         va_end(args);
54         if (n >= sizeof(buffer)-4)
55                 die("protocol error: impossibly long line");
56         n += 4;
57         buffer[0] = hex(n >> 12);
58         buffer[1] = hex(n >> 8);
59         buffer[2] = hex(n >> 4);
60         buffer[3] = hex(n);
61         safe_write(fd, buffer, n);
62 }
64 static void safe_read(int fd, void *buffer, unsigned size)
65 {
66         int n = 0;
68         while (n < size) {
69                 int ret = xread(fd, buffer + n, size - n);
70                 if (ret < 0)
71                         die("read error (%s)", strerror(errno));
72                 if (!ret)
73                         die("unexpected EOF");
74                 n += ret;
75         }
76 }
78 int packet_read_line(int fd, char *buffer, unsigned size)
79 {
80         int n;
81         unsigned len;
82         char linelen[4];
84         safe_read(fd, linelen, 4);
86         len = 0;
87         for (n = 0; n < 4; n++) {
88                 unsigned char c = linelen[n];
89                 len <<= 4;
90                 if (c >= '0' && c <= '9') {
91                         len += c - '0';
92                         continue;
93                 }
94                 if (c >= 'a' && c <= 'f') {
95                         len += c - 'a' + 10;
96                         continue;
97                 }
98                 if (c >= 'A' && c <= 'F') {
99                         len += c - 'A' + 10;
100                         continue;
101                 }
102                 die("protocol error: bad line length character");
103         }
104         if (!len)
105                 return 0;
106         len -= 4;
107         if (len >= size)
108                 die("protocol error: bad line length %d", len);
109         safe_read(fd, buffer, len);
110         buffer[len] = 0;
111         return len;